簡體   English   中英

Node.js:復制 csv 時文件大小的差異

[英]Node.js: difference in file size when copying csv

我有以下代碼,我從 CSV 讀取並寫入另一個 CSV。 在寫入另一個文件之前,我將轉換一些數據,但作為測試,我運行了代碼,發現源文件和目標文件之間存在細微差別,而沒有事件更改文件的任何內容。

  for(const m of metadata) {
      tempm = m;
      fname = path;
      const pipelineAsync = promisify(pipeline);
      if(m.path) {
        await pipelineAsync(
          fs.createReadStream(m.path),
          csv.parse({delimiter: '\t', columns: true}),
          csv.transform((input) => {
            return Object.assign({}, input);
          }),
          csv.stringify({header: true, delimiter: '\t'}),
          fs.createWriteStream(fname, {encoding: 'utf16le'})
        )
        let nstats = fs.statSync(fname);
        tempm['transformedPath'] = fname;
        tempm['transformed'] = true;
        tempm['t_size_bytes'] = nstats.size;
      }
  }

例如,我看到,

file a: the source file size is `895631` while after copying destination file size is `898545`
file b: the source file size is `51388` while after copying destination file size is `52161`
file c: the source file size is `13666` while after copying destination file size is `13587`

但是當我不使用轉換時,大小匹配,例如此代碼在源和目標上產生完全相同的文件大小


  for(const m of metadata) {
      tempm = m;
      fname = path;
      const pipelineAsync = promisify(pipeline);
      if(m.path) {
        await pipelineAsync(
          fs.createReadStream(m.path),
          /*csv.parse({delimiter: '\t', columns: true}),
          csv.transform((input) => {
            return Object.assign({}, input);
          }),
          csv.stringify({header: true, delimiter: '\t'}),*/
          fs.createWriteStream(fname, {encoding: 'utf16le'})
        )
        let nstats = fs.statSync(fname);
        tempm['transformedPath'] = fname;
        tempm['transformed'] = true;
        tempm['t_size_bytes'] = nstats.size;
      }
  }

任何人都可以幫助確定我需要將哪些選項傳遞給 csv 轉換,以便正確進行復制。

我正在做這個測試以確保我不會丟失大文件中的任何數據。

謝謝。

更新 1:我還檢查了兩個文件的編碼是否相同。

更新 2:我注意到源文件有CRLF和目標文件有LF 有沒有辦法我可以使用 node.js 保持相同,或者它是否依賴於OS

更新 3:看起來問題是EOL ,我看到源文件有CRLF而目標文件/轉換后的文件有LF 我現在需要找到一種方法來指定我上面的代碼,以便EOL是一致的

您需要設置 EOL 配置:

const { pipeline } = require('stream')
const { promisify } = require('util')
const fs = require('fs')
const csv = require('csv')
const os = require('os')


;(async function () {
  const pipelineAsync = promisify(pipeline)
  await pipelineAsync(
    fs.createReadStream('out'),
    csv.parse({ delimiter: ',', columns: true }),
    csv.transform((input) => {
      return Object.assign({}, input)
    }),
    // Here the trick:
    csv.stringify({ eol: true, record_delimiter: os.EOL, header: true, delimiter: '\t' }),
    fs.createWriteStream('out2', { encoding: 'utf16le' })
  )
})()

您也可以使用\r\n或任何您需要$-new-line\n

閱讀源代碼可以發現此設置。

這種差異的兩個主要來源是:

  1. EOL 樣式(unix 或 ms-dos)
  2. 文件編碼

使用簡單的 unix file命令行實用程序,您可以檢查源文件的編碼和 EOL 樣式。 確保對 dest 文件使用相同的選項,任何差異都應該消失。

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM