چگونه یک فایل CSV بزرگ را با جاوا ۸ و جریان داده بخوانیم
سناریویی در نظر بگیرید که قصد دارید یک فایل csv بزرگ (در حدود 90MB) را بخوانید و یک شئ جاوا برای هر خط آن بسازید. چگونه این کار به شکل عملی امکانپذیر است؟
فرض کنید که مسیر فایل csv را میدانید.
کد زیر فایل را میخواند و به ازای هر خط یک شئ جاوا میسازد.
private List<YourJavaItem> processInputFile(String inputFilePath) { List<YourJavaItem> inputList = new ArrayList<YourJavaItem>(); try{ File inputF = new File(inputFilePath); InputStream inputFS = new FileInputStream(inputF); BufferedReader br = new BufferedReader(new InputStreamReader(inputFS)); // skip the header of the csv inputList = br.lines().skip(1).map(mapToItem).collect(Collectors.toList()); br.close(); } catch (FileNotFoundException|IOException e) { .... } return inputList ; }
توضیح بعضی از بخشهای کد:
lines(): یک شئ جریانداده برمیگرداند.
skip(1): خط اول فایل csv را به عنوان خط عناوین در نظر گرفته و آن را نادیده میگیرد.
map(mapToItem): تابع mapToItem را برای هر خط از فایل فراخوانی میکند.
collect(Collector.toList()): یک لیست شامل تمام آیتمهایی که با mapToItem ساخته شدهاند میسازد.
حالا تابع mapToItem به شکل زیر خواهد بود:
private Function<String, YourJavaItem> mapToItem = (line) -> { String[] p = line.split(COMMA);// a CSV has comma separated lines YourJavaItem item = new YourJavaItem(); item.setItemNumber(p[0]);//<-- this is the first column in the csv file if (p[3] != null && p[3].trim().length() > 0) { item.setSomeProeprty(p[3]); } //more initialization goes here return item; }
کارایی کد:
از تستهای دستی که انجام گرفته به نظر میرسد خواندن یک فایل csv با حجم ۹۰ مگ با استفاده از راهی که در بالا گفته شد، ۷۰۰ میلی ثانیه در اکلیپس زمان میبرد و احتمالا این مقدار در تولید بهتر هم خواهد بود.
منبع:
CSV has comma separated items not lines
col1,col2,col3
1,2,3
4,5,6
7,8,9
بله درسته، مشکل چیست؟
در واقع هر سطر یک شئ است که در مثال شما صفات col1, col2, col3 برای آن شئ مقداردهی شده است.