Ich finde, dass es als Thema zu genau und zu schwach ist, aber ich habe es geschrieben.
Der PostgreSQL-Kopierbefehl lautet Sie können mit hoher Geschwindigkeit verarbeiten, wenn Sie die Datei in der Tabelle speichern. Obwohl CSV so registriert werden kann, wie es ist, Wenn Sie den Wert vervollständigen möchten
Wenn Sie also in der richtigen Reihenfolge arbeiten, Da das Schreiben in den Speicher zweimal ausgeführt wird (Datei und DB), Ich denke, es ist besser, es zu vereinheitlichen und umzusetzen.
Es sieht so aus in einfachem Schreiben,
public static long copy(Connection conn, String filePath, String tableName) throws Exception {
CopyManager copyManager = new CopyManager((BaseConnection) conn);
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF8"));
String sql = "copy " + tableName + " FROM STDIN WITH DELIMITER ','";
long result = copyManager.copyIn(sql, reader);
reader.close();
return result;
}
Übergeben Sie die Verbindung an CopyManager Erstellen Sie eine Instanz der CSV Reader-Klassenschnittstelle Übergeben Sie es an copyIn und gießen Sie es ein. Zu diesem Zeitpunkt wird davon ausgegangen, dass die CSV die Spaltenstruktur der Tabelle unverändert hat.
Erstellen Sie Ihren eigenen Reader und Ich dachte, ich würde zum Zeitpunkt des Lesens eine Systemspalte hinzufügen. Erstellen Sie eine Reader-Klasse, die die folgende Read-Methode implementiert.
public class CsvFileWithSysColReader extends Reader {
/**Warteschlange zum Speichern von Zeichenketten mit Spalten*/
private final Queue<Character> csvBuffer;
/**Ich werde es mit einem Argument im Reader-Konstruktor von CSV setzen*/
private final BufferedReader reader = new ArrayDeque<>();
//~~ Abkürzung ~~
/**
*Konstrukteur
*
* @param reader Buffered Reader zum Umschließen
* @throws IOException
*/
public CsvFileWithSysColReader(final BufferedReader reader)
throws IOException {
//Es kann gut sein, einen Booleschen Wert wie skipPeader im Argument zu haben, um eine Header-Sprungfunktion zu haben.
this.reader = reader;
}
@Override
public int read(final char[] cbuf, final int off, final int len) throws IOException {
int readCount = len;
//Wenn die Größe des CSV-Lesepuffers geringer ist als die Anzahl der vom Befehl Kopieren gelesenen Stellen, lesen Sie aus der Datei.
while (this.csvBuffer.size() < len) {
//Wenn es der letzte Teil der Datei ist, beenden Sie und geben Sie nur die aktuelle Anzahl von Ziffern zurück.
if (loadLine() == 0) {
readCount = this.csvBuffer.size();
break;
}
}
//Bei einem Lesevorgang wird die Anzahl der Ziffern zurückgegeben.
if (readCount != 0) {
for (int i = off; i < readCount; i++) {
cbuf[i] = this.csvBuffer.poll();
}
return readCount;
} else {
//Wenn nicht, am Ende-Rückgabe 1.
return -1;
}
}
/**
*Zeilenlast
*
* @return Lade Ergebnis Anzahl der Zeichen
* @throws IOException
*/
private int loadLine() throws IOException {
final String line = this.reader.readLine();
if (line == null) {
//Wenn keine Erfassungszeile vorhanden ist, wird 0 zurückgegeben und der Prozess beendet.
return 0;
} else {
//addSysCol: Eine Funktion, die Systemspalten hinzufügt und nach Belieben bearbeitet.
//Es ist auch möglich, eine Fehlerspalte hinzuzufügen, indem Sie hier nachsehen
final String lineWithSysCol= addSysCol(line);
for (int i = 0; i < lineWithSysCol.length(); i++) {
this.csvBuffer.add(lineWithSysCol.charAt(i));
}
return lineWithSysCol.length();
}
}
//~~ Abkürzung ~~
}
Und so ausführen.
public static long copy(final Connection conn, final String filePath, final String tableName) throws Exception {
final CopyManager copyManager = new CopyManager((BaseConnection) conn);
final Reader reader = new CsvFileWithSysColReader(new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF8")));
final String sql = "copy " + tableName + " FROM STDIN WITH DELIMITER ','";
final long result = copyManager.copyIn(sql, reader);
reader.close();
return result;
}
Die obige Implementierung von CsvFileWithSysColReader.addSysCol (String line) erweitert den Bereich wie folgt.
In der Anwendungsentwicklung E / A ist also oft behoben Wenn Sie mit Interface eine Wrap-Klasse erstellen und dort die Verarbeitung übernehmen Es gibt viele Dinge, die getan werden können.
Apropos Eigentlich habe ich es mit verschiedenen Funktionen implementiert, Ich ließ die Funktion von dort fallen und schrieb nur die Hauptpunkte, Es tut mir leid, wenn es eine Auslassung gibt. .. ..
Recommended Posts