얼마 전에 많은 양의 데이터가 필요했습니다. DBA는 CVS 파일을 제공했지만 각 CVS 파일의 크기는 여러 GB이므로 직접로드됩니다. 데이터베이스는 매우 느리고 메모리가 충분하지 않습니다. 이 기능을 실현하기 위해 파일을 빠르게 분할하는 프로그램이 작성되었습니다.
import org.apache.log4j.logmanager; import org.apache.log4j.logger; import java.io.*; import java.util.*; import java.util.concurrent.*; 공개 클래스 FilesPlitUtil {개인 최종 정적 로거 로그 = logmanager.getLogger (FilesPlitUtil.class); 개인 정적 최종 Long OriginFileSize = 1024 * 1024 * 100; // 100m 개인 정적 최종 int blockfilesize = 1024 * 1024 * 64; // 중국어가 무너지는 것을 방지하려면 2를 N 전력으로 가져 가야합니다/ ** * CVS 파일 분리기 */ 개인 정적 최종 CVSSEPARATOR = '^'; public static void main (String args []) {Long Start = System.CurrentTimeMillis (); try {String filename = "d : //csvtest//aa.csv"; 파일 소스 파일 = 새 파일 (filename); if (sourceFile.Length ()> = originFilesize) {String CvsFilename = filename.replaceall ( "///", "/"); filesplitutil filesplitutil = 새 filesplitutil (); <string> parts = filesplitutil.splitbysize (cvsfilename, blockfilesize); for (string part : parts) {System.out.println ( "PartName IS :"+part); }} system.out.println ( "총 파일 길이" + sourcefile.length () + ", 파일을 분할 시간 :" + (System.CurrentTimeMillis () - 시작) + "ms."); } catch (예외 e) {log.info (e.getStackTrace ()); }} / *** 분할 파일** @param filename 분할 할 완전한 파일 이름을 분할* @param bytesize 분할 파일 이름의 @return 목록* / public list <string> splitbysize (문자열 파일 이름, int bytesize)는 ioexception, {string> parts = new arraylist> (); 파일 = 새 파일 (filename); int count = (int) math.ceil (file.length () / (double) bytesize); int countlen = (count + "") .length (); randomaccessfile raf = 새로운 randomaccessfile (filename, "r"); 긴 총체 = raf.length (); CountdownLatch Latch = New CountdownLatch (Count); for (int i = 0; i <count; i ++) {string partfilename = file.getPath ()+"." + leftPad ((i + 1) + "", countlen, '0') + ".cvs"; int readsize = bytesize; 긴 startpos = (long) i * 바이트 크기; long nextpos = (long) (i+1) * 바이트 크기; if (nextpos> Tetallen) {readsize = (int) (Tetallen-Startpos); } new splitRunnable (readsize, startpos, partfilename, file, latch) .run (); parts.add (partfilename); } latch.await (); // 모든 파일이 쓸 때까지 대기 대기 // 절단 중에 줄이 잘릴 수 있고 모든 분할 파일이 처리 될 수 있습니다. 합병 (부품); 반환 부품; } / ** * 세그먼트 처리 실행 가능 * * @author supeidong * / private class splitrunnable empless runnable {int bytesize; 문자열 partfilename; 파일 원산지; 긴 시작성; CountdownLatch 래치; public splitrunnable (int bytesize, long startpos, 문자열 partfilename, 파일 원산지, countdownlatch latch) {this.startpos = startpos; this.bytesize = bytesize; this.partfilename = partfilename; this.originfile = originfile; this.latch = 래치; } public void run () {randomaccessfile rfile; 출력 스트림 OS; try {rfile = new randomaccessfile (Originfile, "r"); 바이트 [] B = 새로운 바이트 [바이트 크기]; rfile.seek (startpos); // 포인터를 각 "세그먼트"int s = rfile.read (b)의 시작으로 이동합니다. os = new FileOutputStream (partFileName); os.write (b, 0, s); os.flush (); os.close (); latch.countdown (); } catch (ioexception e) {log.error (e.getMessage ()); latch.countdown (); }}} / ** * 컷 라인 병합 * * @param parts * / private void 합병 (list <string> parts) {list <partfile> partfiles = new ArrayList <PartFile> (); {// 분할 테이블 객체를 조립하십시오 (int i = 0; i <parts.size (); i ++) {String partfilename = parts.get (i); 파일 splitfileTemp = 새 파일 (partFileName); if (splitfiletemp.exists ()) {partfile partfile = new partfile (); bufferedReader reader = new bufferedReader (new inputStreamReader (new FileInputStream (splitfileTemp), "GBK"); String firstrow = reader.readline (); 문자열 secondrow = reader.readline (); 문자열 endrow = readlastline (partfilename); partfile.setPartFilename (partfilename); partfile.setfirstrow (Firstrow); partfile.setendrow (endrow); if (i> = 1) {String prepartFile = parts.get (i -1); 문자열 preendrow = readlastline (prepartfile); partfile.setfirstisfull (getCharCount (Firstrow+preendrow)> getCharCount (Secondrow)); } partfiles.add (partfile); reader.close (); }} // (int i = 0; i <partfiles.size.size () -1; i ++) {partfile partfile = partfiles.get (i); partfile partfilenext = partfiles.get (i + 1); StringBuilder sb = new StringBuilder (); if (partfilenext.getFirstisFull ()) {SB.Append ( "/r/n"); sb.append (partfilenext.getfirstrow ()); } else {sb.append (partfilenext.getFirstrow ()); } writeLastLine (partFile.getPartFilename (), sb.toString ()); }} catch (예외 e) {log.error (e.getMessage ()); }} / ** * 문자가 나타나는 횟수를 가져옵니다 * @param s * @return * / private int getCharcount (String s) {int count = 0; for (int i = 0; i <s.length (); i ++) {if (s.charat (i) == cvsseparator) {count ++; }} 반환 수; } / ** * 파일 라인 수를 읽으려면 bufferedInputStream을 사용하여 * @param filename * @return * / public int getFilerow (String filename) 던지기 ioexception {inputStream IS = new bufferedInputStream (new FileInputStream (filename)); 바이트 [] C = 새로운 바이트 [1024]; int count = 0; int readchars = 0; while ((readchars = is.read (c))! = -1) {for (int i = 0; i <readchars; ++ i) {if (c [i] == '/n') ++ count; }} is.close (); 반환 수; } / ** * 마지막 데이터 줄 * @param filename * @return * @throws ioexception * / private string readlastline (string filename)은 ioexception {// randomaccessfile raf = new randomaccessfile (filename, "R") 뒤에서 마지막 데이터 라인을 찾으십시오. 긴 len = raf.length (); 문자열 lastline = ""; if (len! = 0l) {long pos = len -1; while (pos> 0) {pos-; raf.seek (pos); if (raf.readbyte () == '/n') {lastline = raf.readline (); lastline = new String (lastline.getBytes ( "8859_1"), "gbk"); 부서지다; }}}} raf.close (); 마지막으로 반환; } / ** * 데이터의 마지막 줄을 수정 * @param filename * @param laststring * @return * @throws ioexception * / private void writelastline (String filename, string laststring) {try {// 랜덤 액세스 파일 스트림을 열고 읽기 및 쓰기 메소드에 따라 읽고 쓰고 쓰기 (filename); "); // 파일 길이, 바이트 수 긴 filelength = randomfile.length (); // 파일 쓰기 포인터를 파일 끝으로 이동합니다. randomfile.seek (filelength); // gbk는 여기에 추가해야합니다. 그렇지 않으면 randomfile.write (laststring.getBytes ( "gbk")); randomfile.close (); } catch (ioexception e) {log.error (e.getMessage ()); }} / ** * 왼쪽 채우기 * * @param str * @param length * @param ch * @return * / public static string leftpad (String str, int length, char ch) {if (str.length ()> = length) {return str; } char [] chs = new char [길이]; 배열 .fill (chs, ch); char [] src = str.tochararray (); System.ArrayCopy (SRC, 0, CHS, 길이 -SRC.Length, Src.Length); 새 문자열 (CHS)을 반환합니다. } / *** 파일 라인 내부 클래스 병합* / 클래스 partfile {private String partfilename; 개인 문자열 Firstrow; 개인 문자열 endrow; 개인 부울 Firstisfull; public String getPartFilename () {return partfilename; } public void setPartFilename (String partFilename) {this.partFilename = partFilename; } public String getFirstrow () {return firstrow; } public void setfirstrow (String Firstrow) {this.firstrow = firstrow; } public String getendrow () {return endrow; } public void etendrow (String endrow) {this.endrow = endrow; } public boolean getfirstisfull () {return firstisfull; } public void setfirstisfull (boolean firstisfull) {this.firstisfull = firstisfull; }}}위의 내용은이 기사에 관한 모든 것입니다. 모든 사람들이 Java 프로그래밍을 배우는 것이 도움이되기를 바랍니다.