대용량 엑셀 파일을 효율적으로 여는 방법
150MB의 원시트 엑셀파일을 가지고 있습니다.이 파일은 강력한 기계로 여는 데 약 7분이 걸립니다.이 파일은 다음과 같습니다.
# using python
import xlrd
wb = xlrd.open_workbook(file)
sh = wb.sheet_by_index(0)
엑셀 파일을 더 빨리 열 수 있는 방법은 없나요?하둡, 스파크, c, 자바 등 매우 엉뚱한 제안도 받아들일 수 있습니다.이상적으로는 30초 안에 파일을 열 수 있는 방법을 찾고 있어요 만약 그게 허황된 꿈이 아니라면 말이죠또한 위의 예에서는 python을 사용하고 있지만 python일 필요는 없습니다.
주의: 이것은 클라이언트의 Excel 파일입니다.저희가 받기 전에는 다른 포맷으로 변환할 수 없습니다.그것은 우리의 파일이 아니다.
업데이트: 다음 200MB 엑셀 파일을 30초 이내에 여는 코드 작업 예시로 답하면 현상금이 지급됩니다.https://drive.google.com/file/d/0B_CXvCTOo7_2VW9id2VXRWZrbzQ/view?usp=sharing이 파일에는 문자열(col 1), 날짜(col 9) 및 번호(col 11)가 포함되어 있어야 합니다.
Office 제품과 함께 작동하는 대부분의 프로그래밍 언어에는 중간 계층이 있으며, 일반적으로 병목 현상이 발생합니다. 좋은 예로는 PIA/Interop 또는 Open XML SDK를 사용하는 것입니다.
(중간 레이어를 바이패스하여) 낮은 레벨의 데이터를 취득하는 방법 중 하나는 드라이버를 사용하는 것입니다.
약 7분 걸리는 150MB 원시트 엑셀 파일.
제가 할 수 있는 최선의 방법은 130MB 파일을 약 3배 빠른 135초 안에 만드는 것입니다.
Stopwatch sw = new Stopwatch();
sw.Start();
DataSet excelDataSet = new DataSet();
string filePath = @"c:\temp\BigBook.xlsx";
// For .XLSXs we use =Microsoft.ACE.OLEDB.12.0;, for .XLS we'd use Microsoft.Jet.OLEDB.4.0; with "';Extended Properties=\"Excel 8.0;HDR=YES;\"";
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + filePath + "';Extended Properties=\"Excel 12.0;HDR=YES;\"";
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
OleDbDataAdapter objDA = new System.Data.OleDb.OleDbDataAdapter
("select * from [Sheet1$]", conn);
objDA.Fill(excelDataSet);
//dataGridView1.DataSource = excelDataSet.Tables[0];
}
sw.Stop();
Debug.Print("Load XLSX tool: " + sw.ElapsedMilliseconds + " millisecs. Records = " + excelDataSet.Tables[0].Rows.Count);
Windows 7x64, 인텔 i5, 2.3ghz, 8GB RAM, SSD250GB
하드웨어 솔루션도 추천할 수 있다면 표준 HDD를 사용하는 경우 SSD로 해결하십시오.
주의: 회사 방화벽 뒤에 있기 때문에 Excel 스프레드시트의 예를 다운로드할 수 없습니다.
PS. MSDN - 200MB의 데이터를 가진 xlsx 파일을 가져오는 가장 빠른 방법을 참조하십시오. 합의는 OleDB가 가장 빠릅니다.
PS 2. python을 사용한 방법은 다음과 같습니다.http://code.activestate.com/recipes/440661-read-tabular-data-from-excel-spreadsheets-the-fast/
를 사용하여 파일을 30초 만에 읽을 수 있었습니다.NET 코어 및 Open XML SDK.
다음 예제에서는 일치하는 유형의 모든 행과 셀을 포함하는 개체 목록을 반환합니다. 이 개체는 날짜, 숫자 및 텍스트 셀을 지원합니다.이 프로젝트는 https://github.com/xferaa/BigSpreadSheetExample/ (Windows, Linux 및 Mac OS에서 작동해야 하며 Excel 또는 Excel 컴포넌트를 설치할 필요가 없습니다).
public List<List<object>> ParseSpreadSheet()
{
List<List<object>> rows = new List<List<object>>();
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filePath, false))
{
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);
Dictionary<int, string> sharedStringCache = new Dictionary<int, string>();
int i = 0;
foreach (var el in workbookPart.SharedStringTablePart.SharedStringTable.ChildElements)
{
sharedStringCache.Add(i++, el.InnerText);
}
while (reader.Read())
{
if(reader.ElementType == typeof(Row))
{
reader.ReadFirstChild();
List<object> cells = new List<object>();
do
{
if (reader.ElementType == typeof(Cell))
{
Cell c = (Cell)reader.LoadCurrentElement();
if (c == null || c.DataType == null || !c.DataType.HasValue)
continue;
object value;
switch(c.DataType.Value)
{
case CellValues.Boolean:
value = bool.Parse(c.CellValue.InnerText);
break;
case CellValues.Date:
value = DateTime.Parse(c.CellValue.InnerText);
break;
case CellValues.Number:
value = double.Parse(c.CellValue.InnerText);
break;
case CellValues.InlineString:
case CellValues.String:
value = c.CellValue.InnerText;
break;
case CellValues.SharedString:
value = sharedStringCache[int.Parse(c.CellValue.InnerText)];
break;
default:
continue;
}
if (value != null)
cells.Add(value);
}
} while (reader.ReadNextSibling());
if (cells.Any())
rows.Add(cells);
}
}
}
return rows;
}
Windows 10 64비트 상에서 SSD 드라이브, 8GB RAM, 인텔 Core i7-4710 CPU @ 2.50GHz (2코어)를 탑재한 3년 된 노트북으로 프로그램을 실행했습니다.
파일 전체를 열어서 문자열로 해석하는 데 걸리는 시간은 30초 미만이지만, 지난번 편집 예시와 같이 개체를 사용할 경우 시간이 거의 50초 가까이 걸립니다.Linux 를 사용하면, 서버에서는 30 초 가까이 됩니다.
여기서 설명하는 바와 같이 SAX 접근 방식을 사용하는 것이 요령입니다.
https://msdn.microsoft.com/en-us/library/office/gg575571.aspx
예를 들어 Excel을 CSV 파일처럼 단순하게 만들려면(https://drive.google.com/file/d/0B_CXvCTOo7_2UVZxbnpRaEVnaFk/view?usp=sharing), 파일을 zip 파일로 열고 모든 xml을 직접 읽을 수 있습니다.
인텔 i5 4460, 12GB RAM, SSD Samsung EVO PRO.
메모리 메모리가 많은 경우:이 코드는 RAM이 많이 필요하지만 20~25초 소요됩니다.(파라미터 -Xmx7g 필요)
package com.devsaki.opensimpleexcel;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.zip.ZipFile;
public class Multithread {
public static final char CHAR_END = (char) -1;
public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
String excelFile = "C:/Downloads/BigSpreadsheetAllTypes.xlsx";
ZipFile zipFile = new ZipFile(excelFile);
long init = System.currentTimeMillis();
ExecutorService executor = Executors.newFixedThreadPool(4);
char[] sheet1 = readEntry(zipFile, "xl/worksheets/sheet1.xml").toCharArray();
Future<Object[][]> futureSheet1 = executor.submit(() -> processSheet1(new CharReader(sheet1), executor));
char[] sharedString = readEntry(zipFile, "xl/sharedStrings.xml").toCharArray();
Future<String[]> futureWords = executor.submit(() -> processSharedStrings(new CharReader(sharedString)));
Object[][] sheet = futureSheet1.get();
String[] words = futureWords.get();
executor.shutdown();
long end = System.currentTimeMillis();
System.out.println("only read: " + (end - init) / 1000);
///Doing somethin with the file::Saving as csv
init = System.currentTimeMillis();
try (PrintWriter writer = new PrintWriter(excelFile + ".csv", "UTF-8");) {
for (Object[] rows : sheet) {
for (Object cell : rows) {
if (cell != null) {
if (cell instanceof Integer) {
writer.append(words[(Integer) cell]);
} else if (cell instanceof String) {
writer.append(toDate(Double.parseDouble(cell.toString())));
} else {
writer.append(cell.toString()); //Probably a number
}
}
writer.append(";");
}
writer.append("\n");
}
}
end = System.currentTimeMillis();
System.out.println("Main saving to csv: " + (end - init) / 1000);
}
private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
private static final LocalDateTime INIT_DATE = LocalDateTime.parse("1900-01-01T00:00:00+00:00", formatter).plusDays(-2);
//The number in excel is from 1900-jan-1, so every number time that you get, you have to sum to that date
public static String toDate(double s) {
return formatter.format(INIT_DATE.plusSeconds((long) ((s*24*3600))));
}
public static String readEntry(ZipFile zipFile, String entry) throws IOException {
System.out.println("Initialing readEntry " + entry);
long init = System.currentTimeMillis();
String result = null;
try (BufferedReader br = new BufferedReader(new InputStreamReader(zipFile.getInputStream(zipFile.getEntry(entry)), Charset.forName("UTF-8")))) {
br.readLine();
result = br.readLine();
}
long end = System.currentTimeMillis();
System.out.println("readEntry '" + entry + "': " + (end - init) / 1000);
return result;
}
public static String[] processSharedStrings(CharReader br) throws IOException {
System.out.println("Initialing processSharedStrings");
long init = System.currentTimeMillis();
String[] words = null;
char[] wordCount = "Count=\"".toCharArray();
char[] token = "<t>".toCharArray();
String uniqueCount = extractNextValue(br, wordCount, '"');
words = new String[Integer.parseInt(uniqueCount)];
String nextWord;
int currentIndex = 0;
while ((nextWord = extractNextValue(br, token, '<')) != null) {
words[currentIndex++] = nextWord;
br.skip(11); //you can skip at least 11 chars "/t></si><si>"
}
long end = System.currentTimeMillis();
System.out.println("SharedStrings: " + (end - init) / 1000);
return words;
}
public static Object[][] processSheet1(CharReader br, ExecutorService executorService) throws IOException, ExecutionException, InterruptedException {
System.out.println("Initialing processSheet1");
long init = System.currentTimeMillis();
char[] dimensionToken = "dimension ref=\"".toCharArray();
String dimension = extractNextValue(br, dimensionToken, '"');
int[] sizes = extractSizeFromDimention(dimension.split(":")[1]);
br.skip(30); //Between dimension and next tag c exists more or less 30 chars
Object[][] result = new Object[sizes[0]][sizes[1]];
int parallelProcess = 8;
int currentIndex = br.currentIndex;
CharReader[] charReaders = new CharReader[parallelProcess];
int totalChars = Math.round(br.chars.length / parallelProcess);
for (int i = 0; i < parallelProcess; i++) {
int endIndex = currentIndex + totalChars;
charReaders[i] = new CharReader(br.chars, currentIndex, endIndex, i);
currentIndex = endIndex;
}
Future[] futures = new Future[parallelProcess];
for (int i = charReaders.length - 1; i >= 0; i--) {
final int j = i;
futures[i] = executorService.submit(() -> inParallelProcess(charReaders[j], j == 0 ? null : charReaders[j - 1], result));
}
for (Future future : futures) {
future.get();
}
long end = System.currentTimeMillis();
System.out.println("Sheet1: " + (end - init) / 1000);
return result;
}
public static void inParallelProcess(CharReader br, CharReader back, Object[][] result) {
System.out.println("Initialing inParallelProcess : " + br.identifier);
char[] tokenOpenC = "<c r=\"".toCharArray();
char[] tokenOpenV = "<v>".toCharArray();
char[] tokenAttributS = " s=\"".toCharArray();
char[] tokenAttributT = " t=\"".toCharArray();
String v;
int firstCurrentIndex = br.currentIndex;
boolean first = true;
while ((v = extractNextValue(br, tokenOpenC, '"')) != null) {
if (first && back != null) {
int sum = br.currentIndex - firstCurrentIndex - tokenOpenC.length - v.length() - 1;
first = false;
System.out.println("Adding to : " + back.identifier + " From : " + br.identifier);
back.plusLength(sum);
}
int[] indexes = extractSizeFromDimention(v);
int s = foundNextTokens(br, '>', tokenAttributS, tokenAttributT);
char type = 's'; //3 types: number (n), string (s) and date (d)
if (s == 0) { // Token S = number or date
char read = br.read();
if (read == '1') {
type = 'n';
} else {
type = 'd';
}
} else if (s == -1) {
type = 'n';
}
String c = extractNextValue(br, tokenOpenV, '<');
Object value = null;
switch (type) {
case 'n':
value = Double.parseDouble(c);
break;
case 's':
try {
value = Integer.parseInt(c);
} catch (Exception ex) {
System.out.println("Identifier Error : " + br.identifier);
}
break;
case 'd':
value = c.toString();
break;
}
result[indexes[0] - 1][indexes[1] - 1] = value;
br.skip(7); ///v></c>
}
}
static class CharReader {
char[] chars;
int currentIndex;
int length;
int identifier;
public CharReader(char[] chars) {
this.chars = chars;
this.length = chars.length;
}
public CharReader(char[] chars, int currentIndex, int length, int identifier) {
this.chars = chars;
this.currentIndex = currentIndex;
if (length > chars.length) {
this.length = chars.length;
} else {
this.length = length;
}
this.identifier = identifier;
}
public void plusLength(int n) {
if (this.length + n <= chars.length) {
this.length += n;
}
}
public char read() {
if (currentIndex >= length) {
return CHAR_END;
}
return chars[currentIndex++];
}
public void skip(int n) {
currentIndex += n;
}
}
public static int[] extractSizeFromDimention(String dimention) {
StringBuilder sb = new StringBuilder();
int columns = 0;
int rows = 0;
for (char c : dimention.toCharArray()) {
if (columns == 0) {
if (Character.isDigit(c)) {
columns = convertExcelIndex(sb.toString());
sb = new StringBuilder();
}
}
sb.append(c);
}
rows = Integer.parseInt(sb.toString());
return new int[]{rows, columns};
}
public static int foundNextTokens(CharReader br, char until, char[]... tokens) {
char character;
int[] indexes = new int[tokens.length];
while ((character = br.read()) != CHAR_END) {
if (character == until) {
break;
}
for (int i = 0; i < indexes.length; i++) {
if (tokens[i][indexes[i]] == character) {
indexes[i]++;
if (indexes[i] == tokens[i].length) {
return i;
}
} else {
indexes[i] = 0;
}
}
}
return -1;
}
public static String extractNextValue(CharReader br, char[] token, char until) {
char character;
StringBuilder sb = new StringBuilder();
int index = 0;
while ((character = br.read()) != CHAR_END) {
if (index == token.length) {
if (character == until) {
return sb.toString();
} else {
sb.append(character);
}
} else {
if (token[index] == character) {
index++;
} else {
index = 0;
}
}
}
return null;
}
public static int convertExcelIndex(String index) {
int result = 0;
for (char c : index.toCharArray()) {
result = result * 26 + ((int) c - (int) 'A' + 1);
}
return result;
}
}
오래된 답변(Xms7g 파라미터는 필요없으므로 메모리 절약):HDD로 예제 파일을 열고 읽는 데 걸리는 시간은 약 35초(200MB)이며, SDD는 조금 더 짧은 시간(30초)입니다.
코드는 https://github.com/csaki/OpenSimpleExcelFast.git 입니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.zip.ZipFile;
public class Launcher {
public static final char CHAR_END = (char) -1;
public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
long init = System.currentTimeMillis();
String excelFile = "D:/Downloads/BigSpreadsheet.xlsx";
ZipFile zipFile = new ZipFile(excelFile);
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<String[]> futureWords = executor.submit(() -> processSharedStrings(zipFile));
Future<Object[][]> futureSheet1 = executor.submit(() -> processSheet1(zipFile));
String[] words = futureWords.get();
Object[][] sheet1 = futureSheet1.get();
executor.shutdown();
long end = System.currentTimeMillis();
System.out.println("Main only open and read: " + (end - init) / 1000);
///Doing somethin with the file::Saving as csv
init = System.currentTimeMillis();
try (PrintWriter writer = new PrintWriter(excelFile + ".csv", "UTF-8");) {
for (Object[] rows : sheet1) {
for (Object cell : rows) {
if (cell != null) {
if (cell instanceof Integer) {
writer.append(words[(Integer) cell]);
} else if (cell instanceof String) {
writer.append(toDate(Double.parseDouble(cell.toString())));
} else {
writer.append(cell.toString()); //Probably a number
}
}
writer.append(";");
}
writer.append("\n");
}
}
end = System.currentTimeMillis();
System.out.println("Main saving to csv: " + (end - init) / 1000);
}
private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
private static final LocalDateTime INIT_DATE = LocalDateTime.parse("1900-01-01T00:00:00+00:00", formatter).plusDays(-2);
//The number in excel is from 1900-jan-1, so every number time that you get, you have to sum to that date
public static String toDate(double s) {
return formatter.format(INIT_DATE.plusSeconds((long) ((s*24*3600))));
}
public static Object[][] processSheet1(ZipFile zipFile) throws IOException {
String entry = "xl/worksheets/sheet1.xml";
Object[][] result = null;
char[] dimensionToken = "dimension ref=\"".toCharArray();
char[] tokenOpenC = "<c r=\"".toCharArray();
char[] tokenOpenV = "<v>".toCharArray();
char[] tokenAttributS = " s=\"".toCharArray();
char[] tokenAttributT = " t=\"".toCharArray();
try (BufferedReader br = new BufferedReader(new InputStreamReader(zipFile.getInputStream(zipFile.getEntry(entry)), Charset.forName("UTF-8")))) {
String dimension = extractNextValue(br, dimensionToken, '"');
int[] sizes = extractSizeFromDimention(dimension.split(":")[1]);
br.skip(30); //Between dimension and next tag c exists more or less 30 chars
result = new Object[sizes[0]][sizes[1]];
String v;
while ((v = extractNextValue(br, tokenOpenC, '"')) != null) {
int[] indexes = extractSizeFromDimention(v);
int s = foundNextTokens(br, '>', tokenAttributS, tokenAttributT);
char type = 's'; //3 types: number (n), string (s) and date (d)
if (s == 0) { // Token S = number or date
char read = (char) br.read();
if (read == '1') {
type = 'n';
} else {
type = 'd';
}
} else if (s == -1) {
type = 'n';
}
String c = extractNextValue(br, tokenOpenV, '<');
Object value = null;
switch (type) {
case 'n':
value = Double.parseDouble(c);
break;
case 's':
value = Integer.parseInt(c);
break;
case 'd':
value = c.toString();
break;
}
result[indexes[0] - 1][indexes[1] - 1] = value;
br.skip(7); ///v></c>
}
}
return result;
}
public static int[] extractSizeFromDimention(String dimention) {
StringBuilder sb = new StringBuilder();
int columns = 0;
int rows = 0;
for (char c : dimention.toCharArray()) {
if (columns == 0) {
if (Character.isDigit(c)) {
columns = convertExcelIndex(sb.toString());
sb = new StringBuilder();
}
}
sb.append(c);
}
rows = Integer.parseInt(sb.toString());
return new int[]{rows, columns};
}
public static String[] processSharedStrings(ZipFile zipFile) throws IOException {
String entry = "xl/sharedStrings.xml";
String[] words = null;
char[] wordCount = "Count=\"".toCharArray();
char[] token = "<t>".toCharArray();
try (BufferedReader br = new BufferedReader(new InputStreamReader(zipFile.getInputStream(zipFile.getEntry(entry)), Charset.forName("UTF-8")))) {
String uniqueCount = extractNextValue(br, wordCount, '"');
words = new String[Integer.parseInt(uniqueCount)];
String nextWord;
int currentIndex = 0;
while ((nextWord = extractNextValue(br, token, '<')) != null) {
words[currentIndex++] = nextWord;
br.skip(11); //you can skip at least 11 chars "/t></si><si>"
}
}
return words;
}
public static int foundNextTokens(BufferedReader br, char until, char[]... tokens) throws IOException {
char character;
int[] indexes = new int[tokens.length];
while ((character = (char) br.read()) != CHAR_END) {
if (character == until) {
break;
}
for (int i = 0; i < indexes.length; i++) {
if (tokens[i][indexes[i]] == character) {
indexes[i]++;
if (indexes[i] == tokens[i].length) {
return i;
}
} else {
indexes[i] = 0;
}
}
}
return -1;
}
public static String extractNextValue(BufferedReader br, char[] token, char until) throws IOException {
char character;
StringBuilder sb = new StringBuilder();
int index = 0;
while ((character = (char) br.read()) != CHAR_END) {
if (index == token.length) {
if (character == until) {
return sb.toString();
} else {
sb.append(character);
}
} else {
if (token[index] == character) {
index++;
} else {
index = 0;
}
}
}
return null;
}
public static int convertExcelIndex(String index) {
int result = 0;
for (char c : index.toCharArray()) {
result = result * 26 + ((int) c - (int) 'A' + 1);
}
return result;
}
}
라이브러리는 데할 수 Python의 Panda를 로드하는 데 사용할 수 있습니다..xlsx
파일 속도가 상당히 느려집니다(예: 를 사용).
한 가지 방법은 Python을 사용하여 Excel 자체를 사용하여 파일을 CSV로 자동 변환한 다음 Panda를 사용하여 결과 CSV 파일을 로드하는 것입니다.그러면 속도가 30초 미만으로 향상됩니다.
import win32com.client as win32
import pandas as pd
from datetime import datetime
print ("Starting")
start = datetime.now()
# Use Excel to load the xlsx file and save it in csv format
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(r'c:\full path\BigSpreadsheet.xlsx')
excel.DisplayAlerts = False
wb.DoNotPromptForConvert = True
wb.CheckCompatibility = False
print('Saving')
wb.SaveAs(r'c:\full path\temp.csv', FileFormat=6, ConflictResolution=2)
excel.Application.Quit()
# Use Pandas to load the resulting CSV file
print('Loading CSV')
df = pd.read_csv(r'c:\full path\temp.csv', dtype=str)
print(df.shape)
print("Done", datetime.now() - start)
은 ''를 하면 알 수.dtype
★★★★★★★★★★★★★★★★★」converters
★★★★★★★★★★★★★★★★★」parse_dates
:
df = pd.read_csv(r'c:\full path\temp.csv', dtype=str, converters={10:int}, parse_dates=[8], infer_datetime_format=True)
'다', '다', '다'도 지정해야 합니다.infer_datetime_format=True
이렇게 하면 날짜 변환이 매우 빨라집니다.
nfer_datetime_format
False: " " , " " FalseTrue 및 parse_dates가 활성화되어 있는 경우 팬더는 컬럼 내의 datetime 문자열 형식을 추론하려고 시도하고 추론할 수 있는 경우 보다 빠른 해석 방법으로 전환합니다.경우에 따라서는 해석 속도가 5~10배 향상될 수 있습니다.
, 「」도 해 주세요.dayfirst=True
가 DD/MM/YYYY
.
컬럼 ★★★★
하면 되는 1 9 11
후, 「자원을 하다」를 하면, 더 할 수 있습니다usecols=[0, 8, 10]
음음음같 뭇매하다
df = pd.read_csv(r'c:\full path\temp.csv', dtype=str, converters={10:int}, parse_dates=[1], dayfirst=True, infer_datetime_format=True, usecols=[0, 8, 10])
그 결과 데이터 프레임에는 그 3개의 데이터 열만 포함됩니다.
RAM 라라 ram ram
RAM 드라이브를 사용하여 임시 CSV 파일을 저장하면 로드 시간이 더욱 빨라집니다.
주의: Excel을 사용할 수 있는 Windows PC를 사용하고 있는 것을 전제로 하고 있습니다.
노트북 (인텔 i7 4 코어, 16 GB RAM)의 최대 40 초만에 파일을 로드할 수 있는 Java 프로그램의 샘플을 작성했습니다.
https://github.com/skadyan/largefile
이 프로그램은 Apache POI 라이브러리를 사용하여 XSSF SAX API를 사용하여 .xlsx 파일을 로드합니다.
인터페이스 " " " "com.stackoverlfow.largefile.RecordHandler
구현은 Excel에서 로드된 데이터를 처리하기 위해 사용할 수 있습니다.에서는 3개의 입니다.
- sheetname : 문자열, 엑셀시트명
- 행 번호: int, 데이터 행 번호
- ★★★★★★★★★★★★★★★★★」
data map
셀 및 값: Excel: Excel 형식 셀 값
★★★★com.stackoverlfow.largefile.Main
에, 이 인터페이스의 기본적인 실장을 나타냅니다.이러한 실장은 콘솔에 행 번호만 출력합니다.
갱신하다
Woodstox 파서는 표준보다 성능이 좋은 것 같습니다.SAXReader
(된 코드 (repo's 'repo's 'repo's 'repo')
, 요건을 만족시키기 , 할 수 .org.apache.poi...XSSFSheetXMLHandler
구현에서는 보다 최적화된 문자열/텍스트 값 처리를 구현할 수 있으며 불필요한 텍스트 형식 지정 작업을 건너뛸 수 있습니다.
Dell Precision T1700 워크스테이션을 사용하고 있으며, c#을 사용하여 파일을 열고 내용을 읽을 수 있었습니다.표준 코드를 사용하여 인터오퍼레이션 서비스를 사용하여 워크북을 여는 것만으로 약 24초 만에 파일을 열 수 있었습니다.Microsoft Excel 15.0 오브젝트 라이브러리에 대한 참조를 사용하는 것은 제 코드입니다.
사용 설명:
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
워크북을 열고 읽는 코드:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
Excel.Application xlApp;
Excel.Workbook wb;
Excel.Worksheet ws;
xlApp = new Excel.Application();
xlApp.Visible = false;
xlApp.ScreenUpdating = false;
wb = xlApp.Workbooks.Open(@"Desired Path of workbook\Copy of BigSpreadsheet.xlsx");
ws = wb.Sheets["Sheet1"];
//string rng = ws.get_Range("A1").Value;
MessageBox.Show(ws.get_Range("A1").Value);
Marshal.FinalReleaseComObject(ws);
wb.Close();
Marshal.FinalReleaseComObject(wb);
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
파이썬C SAX됩니다('C'를 사용).lxml
오버, " " " "libxml2
from __future__ import print_function
from lxml import etree
import time
start_ts = time.time()
for data in etree.iterparse(open('xl/worksheets/sheet1.xml'), events=('start',),
collect_ids=False, resolve_entities=False,
huge_tree=True):
pass
print(time.time() - start_ts)
출력 예: 27.2134890556
참고로 엑셀 자체는 워크북을 로드하는 데 40초 정도 걸립니다.
c# 및 ole 솔루션에는 아직 병목 현상이 있습니다.그래서 나는 그것을 c++와 ado로 테스트한다.
_bstr_t connStr(makeConnStr(excelFile, header).c_str());
TESTHR(pRec.CreateInstance(__uuidof(Recordset)));
TESTHR(pRec->Open(sqlSelectSheet(connStr, sheetIndex).c_str(), connStr, adOpenStatic, adLockOptimistic, adCmdText));
while(!pRec->adoEOF)
{
for(long i = 0; i < pRec->Fields->GetCount(); ++i)
{
_variant_t v = pRec->Fields->GetItem(i)->Value;
if(v.vt == VT_R8)
num[i] = v.dblVal;
if(v.vt == VT_BSTR)
str[i] = v.bstrVal;
++cellCount;
}
pRec->MoveNext();
}
i5-4460과 HDD 기계에서는 xls의 50만 셀이 1.5초 걸립니다.그러나 xlsx의 동일한 데이터는 2.829s.so를 사용합니다. 30대 미만의 데이터를 조작할 수도 있습니다.
30대 미만이 필요한 경우 RAM 드라이브를 사용하여 파일 IO를 줄입니다.그러면 공정이 상당히 개선됩니다.테스트하기 위해 당신의 데이터를 다운받을 수 없으니 결과를 알려주세요.
부하/동작 시간을 크게 단축하는 또 다른 방법은 RAMDrive입니다.
파일을 저장할 충분한 공간과 10%의 RAMDrive를 만듭니다.20%의 여유 공간...
RAMDrive용 파일을 복사...
거기서 파일 로드...드라이브 및 파일 시스템에 따라 속도가 크게 향상됩니다.
내가 가장 좋아하는 것은 IMDisk 툴킷이다.
(https://sourceforge.net/projects/imdisk-toolkit/)에는 모든 것을 스크립팅하는 파워풀한 명령줄이 있습니다.
SoftPerfect ramdisk도 추천합니다.
(http://www.majorgeeks.com/files/details/softperfect_ram_disk.html)
OS에 따라 다릅니다.
파일을 여는 시스템에 대한 자세한 정보를 알고 싶습니다.어쨌든:
.
오피스 ★★★★★★★★★★★★★★★★★★★★★★★★★★★」"
가지고 있다면...★★★★★★★★★★★…
이 훨씬 .
xlrd 버전 0.7.1 이후 사용 가능한 워크시트를 온디맨드 방식으로 로드해 보셨습니까?
는 합격이 합니다.on_demand=True
에 접속합니다.
xlrd.open_workbook(파일명=없음, 로그파일=<_io).TextIOWrapper name='mode='w' 인코딩='UTF-8'', 상세도=0, use_mmap=1, file_contents=None, encoding_override=None, formating_info=False, on_demand=False, ragged_rows=False)
xlsx 파일을 읽기 위해 찾은 다른 잠재적인 python 솔루션:
- 'xl/sharedStrings.xml' 및 'xl/worksheets/sheet1.xml'에서 raw xml을 읽습니다.
대용량 파일의 메모리 사용량이 최적화되었다고 주장하는 Openpyxl 라이브러리의 읽기 전용 모드를 사용해 보십시오.
from openpyxl import load_workbook wb = load_workbook(filename='large_file.xlsx', read_only=True) ws = wb['big_data'] for row in ws.rows: for cell in row: print(cell.value)
Windows 를 실행하고 있는 경우는, PyWin32 와 Excel 를 사용할 수 있습니다.응용 프로그램'
import time import win32com.client as win32 def excel(): xl = win32.gencache.EnsureDispatch('Excel.Application') ss = xl.Workbooks.Add() ...
언급URL : https://stackoverflow.com/questions/46373895/how-to-open-a-huge-excel-file-efficiently
'programing' 카테고리의 다른 글
오류: "INSERT EXEC 문을 중첩할 수 없습니다." 및 "INSERT-EXEC 문 내에서 ROLLBLL 문을 사용할 수 없습니다."어떻게 해결할까요? (0) | 2023.04.09 |
---|---|
Swift3에서 fileprivate와 private를 구별하는 좋은 예는 무엇입니까? (0) | 2023.04.09 |
모든 열거값을 배열로 가져오는 방법 (0) | 2023.04.09 |
UITableView에서 자동 레이아웃을 사용하여 동적 셀 레이아웃 및 가변 열 높이 설정 (0) | 2023.04.09 |
@testable 사용 시 '모듈이 테스트용으로 컴파일되지 않았습니다' (0) | 2023.04.09 |