我有多個 100MB 原始檔案,其中包含 CSV 格式的一系列用戶活動。我只想下載檔案的前 100 行。
問題是每個檔案可能有不同的 CSV 標題列和資料值,因為它們是來自使用不同活動跟蹤提供程式的多個子域的用戶活動。這意味著每行可以是 50 個字符長或 500 個字符長,在我全部閱讀之前是未知的。
S3 支持getObject帶有引數的 API Range,您可以使用該引數下載檔案的特定范圍 XX 位元組。
https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html#API_GetObject_RequestSyntax
如果我使用這個 API 決議前 1Mb 的檔案,迭代每個位元組直到我看到 100 個新行字符\n,這在技術上可行嗎?對于這種方法,我有什么需要注意的嗎?(例如多位元組字符?)
uj5u.com熱心網友回復:
沒有內置方法,位元組范圍提取是最好的方法。
由于您不確定每種情況下的標題或行長,下載 1MB 塊直到您有 100 行是一種安全有效的方法。
多位元組字符等在此級別并不重要,您只是希望在 100 個\n字符后停止閱讀。但是,根據您檔案的來源,我也會意識到\r\n并且\r是有效的行尾。
我撰寫了下面的 Java 代碼來獲取最后一個位元組,請隨意使用它作為獲取第 一個n位元組的起點: n
public String getLastBytesOfObjectAsString(String bucket, String key, long lastBytesCount) {
try {
final ObjectMetadata objectMetadata = client.getObjectMetadata(bucket, key);
final long fileSizeInBytes = objectMetadata.getContentLength();
long rangeStart = fileSizeInBytes - lastBytesCount;
if (rangeStart < 0) {
rangeStart = 0;
}
final GetObjectRequest getObjectRequest =
new GetObjectRequest(bucket, key).withRange(rangeStart);
try (S3Object s3Object = client.getObject(getObjectRequest);
InputStream inputStream = s3Object.getObjectContent()) {
return new String(inputStream.readAllBytes());
}
} catch (Exception ex) {
...
}
}
uj5u.com熱心網友回復:
您可以像這樣使用 smart_open:
from smart_open import open
with open('s3://bucket/path/file.csv', 'r') as f:
csv_reader = csv.DictReader(f, delimiter=',')
data = ''
for i, row in enumerate(csv_reader):
data = row '\n'
if i > 100:
store(data)
您將需要在本地計算機中打開另一個具有寫入權限的檔案,以存盤 100 行或任意數量的行。如果您想要多個檔案的第一行,您可以執行相同的操作,但使用 boto3 函式列出檔案并將路徑/檔案名發送到使用 smart_open 的函式。
s3client = boto3.client('s3')
listObj = s3client.list_objects_v2(Bucket=bucket, Prefix=prefix)
for obj in listObj['Contents']:
smart_function(obj['Key'])
obj['Key'] 包含該 Bucket Path(Prefix) 中每個檔案的路徑和檔案名
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/475890.html
