Frage Schreiben Sie große Textdateidaten in Excel


Ich lese eine Textdatei, die mit einigen Begrenzern getrennt ist.

Beispiel für den Inhalt meiner Textdatei

Avc def efg jksjd
1 2 3 5
3 4 6 0

Zeile für Zeile und halten Sie es im Speicher mit hashmap mit Zeilennummern als Schlüssel des Integer-Typs und jede Zeile der Textdatei als List-Objekt

Bedenken Sie, meine Karte würde solche Informationen speichern

Ganzzahlliste

1 [Avc def efg jksjd]

Ich verwende Apache POI, um in Excel zu schreiben. Wenn ich mit Apache POI in Excel schreibe, folge ich diesem Ansatz, hier ist mein Code-Snippet

HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("Sample sheet");
Map<Integer, List<Object>> excelDataHolder = new LinkedHashMap<Integer, List<Object>>();
int rownum = 0;
for (Integer key : keyset) {
            Row row = sheet.createRow(rownum++);
            List<Object> objList = excelHolder.get(key);//excelHolder is my map
            int cellnum = 0;
            for (Object obj : objList) {
                Cell cell = row.createCell(cellnum++);
                    cell.setCellValue((Date) obj);
            }
}

Dies funktioniert ganz gut, wenn die Anzahl der Zeilen / Datensätze, die in Excel geschrieben werden sollen, geringer ist. Stellen Sie sich vor, wenn die Datensätze in Milliarden sind oder wenn die Textdatei mehr Zeilen in 100 000 hat. Ich denke, mein Ansatz scheitert, weil createRow und createCell erstellt mehr als 100 000 Objekte im Heap. Was auch immer das Java sein mag, um api zu übertreffen, ich denke, das Einschreiben (Excel) basiert auf demselben Ansatz, nämlich der Iteration der Sammlung, wie oben gezeigt. Ich habe auch einige Beispiele mit Aspose gemacht, als Ergebnis haben auch das gleiche Problem, denke ich.

  • Erstellen createRow und createCell jedes Mal, wenn sie aufgerufen werden, neue Objekte?
  • Wenn ja, was ist die Alternative? Wie würde ich große Daten schreiben, um mit besserer Leistung zu übertreffen?

5
2018-05-14 08:36


Ursprung


Antworten:


Eine aktuelle Version von Apache-Poi hat sxssf. Schamlose Kopie von der Website

SXSSF (Paket: org.apache.poi.xssf.streaming) ist API-kompatibel   Streaming-Erweiterung von XSSF, die bei sehr großen Tabellen verwendet werden soll   müssen produziert werden, und der Heap-Speicherplatz ist begrenzt. SXSSF erreicht seinen Tiefstwert   Speicherabdruck, indem der Zugriff auf die Zeilen begrenzt wird, die sich in einem   gleitendes Fenster, während XSSF Zugriff auf alle Zeilen im Dokument gewährt.   Ältere Zeilen, die sich nicht mehr im Fenster befinden, können nicht mehr aufgerufen werden   Sie werden auf die Festplatte geschrieben.

Ich hatte es zum Erstellen einer Tabelle mit 1,5 Millionen Zeilen verwendet.


3
2018-05-14 09:42



Ich werde in Bezug auf Aspose.Cells für Java antworten, da Sie es auch versucht haben.

Das Erstellen oder Laden einer sehr großen Excel-Datei erfordert fast immer großen Speicher. Selbst wenn Sie eine Zeile oder mehrere Zeilen gleichzeitig lesen, schreiben Sie den Inhalt immer noch in die Instanz von Workbook, die in den Speicher geladen wird.

Lösung 1 (Nicht gut und sehr begrenzt): Erhöhen Sie die Größe des Heapspeichers. Wenn die maximale Größe des Heapspeichers für Ihre größte Datei ausreicht, wählen Sie sie aus.

Lösung 2 (Komplex mit manueller Arbeit):  Excel 2007 und höher ermöglicht rund 1 Million Zeilen pro Blatt. Ich würde vorschlagen, dass Sie eine Arbeitsmappe mit nur einem Blatt für 1 Million Zeilen erstellen. Das heißt, wenn Sie 10 Millionen Zeilen in einer Textdatei haben, erstellen Sie 10 separate Excel-Arbeitsmappen.

Später kombinieren Sie sie manuell in einer einzelnen Excel-Arbeitsmappe. Aspose.Cells wird beim Kopieren von Blättern mit solch riesigen Datenmengen eine Speicherausnahme verursachen.

Unten ist das Code-Snippet, das 10 separate Excel-Dateien mit jeweils 1 Million Zeilen erstellt.

import com.aspose.cells.*;
import java.util.*;

public class ExcelLargeTextImport
{
    private static String excelFile = Common.dataDir + "largedata.xlsx";

    public static void main(String args[])
    {
        try
        {
            Common.setLicenses();
            importToExcel();
        }
        catch(Exception ex)
        {
            System.out.println(ex.getMessage());
        }
    }

    private static void importToExcel() throws Exception
    {
        // Process each workbook in a method
        for (int sheetCounter=0 ; sheetCounter<10 ; sheetCounter++)
        {
            saveWorkbook(sheetCounter);
        }
    }

    private static void saveWorkbook(int sheetCounter) throws Exception
    {
        Workbook workbook = new Workbook();
        // Get the first sheet 
        Worksheet worksheet = workbook.getWorksheets().get(0);
        Cells cells = worksheet.getCells();

        // Initialize array list with 1 million records
        ArrayList<String> lines = new ArrayList<String>();
        int rowCount = 1000000;
        for (int i=0 ; i<rowCount ; i++)
        {
            lines.add(i + ";value1;value2;value3");
        }

        long lineNo = 1;
        for (String line : lines)
        {
            // Split the line by delimeter
            String[] values = line.split(";");

            // First cell
            Cell cell = cells.get("A" + lineNo);
            cell.setValue(values[0]);

            // Second cell
            cell = cells.get("B" + lineNo);
            cell.setValue(values[1]);

            // Third cell
            cell = cells.get("C" + lineNo);
            cell.setValue(values[2]);

            // Fourth cell
            cell = cells.get("D" + lineNo);
            cell.setValue(values[2]);

            lineNo++;
        }
        System.out.print(sheetCounter + " ");

        // Saving the Excel file
        workbook.save(excelFile.replace(".xlsx", sheetCounter + ".xlsx"));

        System.out.println("\nExcel file created");
    }
}

PS. Ich bin ein Entwickler Evangelist bei Aspose.


2
2018-05-15 07:25



Warum schreibst du nicht in Blöcken? Hier ist der Ansatz, an den ich denken kann:

  • Lesen Sie Ihre TXT-Datei für einige Zeilen und fügen Sie die Informationen in die Karte ein, während Sie dies tun. Angenommen, Sie haben 100 Zeilen gelesen und Sie haben 100 Einträge in Ihrer Karte.
  • Schreiben Sie diese hundert Einträge in die Excel-Datei, um das Excel zu generieren
  • Leeren Sie Ihre Map oder initialisieren Sie sie neu.
  • Lies nun den nächsten 100 Zeilen Text. Soweit ich weiß, gibt es keine Möglichkeit, direkt auf die 101. Zeile zuzugreifen, ohne die ersten 100 Zeilen zu lesen. So müssen Sie möglicherweise die Datei von Anfang an lesen, aber Sie können die ersten 100 Zeilen vermeiden und den Eintrag in der Karte erstellen.
  • Jetzt aktualisieren Sie die Excel-Datei. Ich denke, dass Sie das Excel mit POI aktualisieren können, wie in diesem Link erwähnt: Bearbeiten Sie vorhandene Excel-Dateien mit jxl api / Apache POI

Wenn Sie diesen Prozess wiederholen. Sie werden sicherlich Ihren Speicherverbrauch sparen, obwohl ich keinen großen Unterschied in der CPU-Auslastung sehe.

Ich hoffe es hilft!


1
2018-05-14 08:50



Hier ist deine Antwort ...

Versuchen Sie diesen einfachen Code & Wenn Sie weitere Zukunft benötigen, können Sie ...

https://Stackoverflow.com/a/16479713/1490962


0
2018-05-14 09:32