Java - Verdeling van groot SQL -tekslêer op Delimeter met behulp van Scanner (OutOfMemoryError)

StackOverflow https://stackoverflow.com/questions/20353915

  •  25-08-2022
  •  | 
  •  

Vra

Ek probeer 'n toepassing skryf wat 'n baie groot SQL -tekslêer ~ 60 GB (257 miljoen reëls) sal neem en elk van die kopie -stellings in aparte tekslêers verdeel.

Die kode wat ek tans gebruik, veroorsaak egter 'n outofemoryerror as gevolg van die lyne wat die skandeerderbufferlimiet oorskry. Die eerste stelling gaan ~ 40 miljoen reëls lank wees.

public static void readFileByDelimeter(String fileName, String requestType, String output) throws FileNotFoundException {

//creating file instance
File file = new File(fileName);

//create scanner instance
Scanner scanner = new Scanner(file, "latin1");

//set custom delimeter
scanner.useDelimeter("COPY");

int number = 0;
System.out.println("Running......");
while (scanner.hasNext()){
    String line = scanner.next();
    if (line.length() > 20) {
        //save statements to seperate SQL files
        PrintWriter out = new PrintWriter("statement" + number + ".sql");
        out.println("COPY" + line.trim());
        out.close();
        }
        number++;
    }

System.out.println("Completed");
}

Gee aanbeveling of dit die verkeerde metode is om hierdie of veranderings aan die bestaande metode uit te voer.

Dank

Was dit nuttig?

Oplossing

Eerstens, waarom u skep of 'n ander proses is om 60 GB -lêer te skep! Miskien moet u na die proses kyk om die proses reg te stel om kleiner SQL -tekslêer te genereer in plaas daarvan om 'n nuwe proses te skep. As dit egter 'n eenmalige ding is wat u moet doen, kan dit goed gaan, maar om u vraag aan te spreek, sou ek die bufferedReader gebruik om die rekords te lees en te verwerk as dit 'n groot lêer is soos u aangedui het.

BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
   // process the line. and write into your output file and close the file.
   }
br.close();

Ander wenke

Ek persoonlik: ek gebruik BufferedReader in die plek van die skandeerder. Dit het ook 'n gerieflike metode () -metode () en ek het nog nooit enige prestasieprobleme daarmee gehad nie. Die enigste ding is dat u met die hand moet kyk of 'n reël wat gelees word, een is wat u wil verwerk, maar dit is gewoonlik so eenvoudig soos om die stringklasmetodes toe te pas.

Dit is nie 'n antwoord op u werklike vraag nie, maar ek beskou dit as 'n ordentlike alternatief vir maklik om te gebruik.

Probeer so iets (maar mooier):

Scanner sc = new Scanner(new BufferedReader(new FileReader(file)));

Dit versier die hele ding met 'n bufferedleser, wat beteken dat nie die inhoud van die lêer tegelyk in die geheue gelaai sal word nie. U kan die skandeerder op dieselfde manier gebruik.

Probeer om 'n bufferedReader te gebruik. Direkte gebruik van skandeerder met lêer- of rou lêerstrome sal die data in die geheue laai en dit nie op GC uitspoel nie. Weddus -benadering is om BufferedReader te gebruik en een reël op 'n slag te lees en handmatige string -tjeks en splitsing te doen. As u op hierdie manier korrek gedoen word, kan u die GC genoeg geleentheid gee om die geheue te herwin indien nodig

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top