【问题标题】:How to read a csv file on angular2 line by line如何逐行读取angular2上的csv文件
【发布时间】:2018-03-26 10:58:44
【问题描述】:

我正在用 angular2 编写一个应用程序,它通过简单的 html 输入读取 csv 文件:

<input type='file' name='userFile' id='file' >

我可以在component.ts访问文件:

ngOnInit() {

   var input = (<HTMLInputElement>document.getElementById("file"));
   input.addEventListener("change", function(event) {
      var files = input.files;
      var len = files.length;

         if (len) {
          console.log("Filename: " + files[0].name);
          console.log("Type: " + files[0].type);
          console.log("Size: " + files[0].size + " bytes");
    
         }

      }, false);

}

如何逐个单元格地读取使用 typescript、JavaScript 或 jQuery 上传的 csv 文件? (这是最好的方法)。

【问题讨论】:

  • 您没有以角度方式附加事件。您不应该使用 dom api 直接访问 dom。您可以查看答案:stackoverflow.com/questions/31746837/…
  • 在 typescript/angular 上做这件事的正确方法是什么?我是新手。
  • 事件函数应该放在哪里?

标签: javascript jquery angular typescript csv


【解决方案1】:

这是一个示例实现角度方式(Angular 版本 2+):

@Component({
  selector: 'app-my-file',
  template: `
   <div class="form-group">
        <input type="file" (change)="onFileSelect($event.target)" name="myfile">
   </div>
  `,
  styles: [``]
})
export class YourComponent implements OnInit {

    csvContent: string;
    
    constructor(){}
    ngOnInit(){
    }

    onFileLoad(fileLoadedEvent) {
            const textFromFileLoaded = fileLoadedEvent.target.result;              
            this.csvContent = textFromFileLoaded;     
            // alert(this.csvContent);
    }

    onFileSelect(input: HTMLInputElement) {
    
      const files = input.files;
      var content = this.csvContent;    
      if (files && files.length) {
         /*
          console.log("Filename: " + files[0].name);
          console.log("Type: " + files[0].type);
          console.log("Size: " + files[0].size + " bytes");
          */
          
          const fileToRead = files[0];
          
          const fileReader = new FileReader();
          fileReader.onload = this.onFileLoad;

          fileReader.readAsText(fileToLoad, "UTF-8");
      }
              
    }
}

Try it on StackBlitz

【讨论】:

  • 谢谢你的例子。我将在示例中的函数中使用阅读器外部实现。
  • 感谢您的帮助。但是我在 onFileLoad 函数中遇到了一个问题:当我在外部类中传入一个方法时,调试器说“this”绑定到 FileReader 类...
【解决方案2】:

除了asmmahmud's answer,我想补充一下如何实际解析文件内容,以便在数组中有行和列(Angular 和 TypeScript)。添加属性:

parsedCsv: string[][];

在他的例子中到YourComponent类。 然后,更新onFileLoad 事件如下:

onFileLoad(fileLoadedEvent): void {
 const csvSeparator = ';';
 const textFromFileLoaded = fileLoadedEvent.target.result;
 this.csvContent = textFromFileLoaded;
 // alert(textFromFileLoaded);

 const txt = textFromFileLoaded;
 const csv = [];
 const lines = txt.split('\n');
 lines.forEach(element => {
   const cols: string[] = element.split(csvSeparator);
   csv.push(cols);
 });
 this.parsedCsv = csv;
 // console.log(this.parsedCsv);
}

现在,您在二维数组parsedCsv 中获得了已解析的 CSV 及其行和列(第 1 维是行,第 2 维是列)。如果需要,您可以替换分隔符 - 默认为分号。

示例:

一个包含

的文件

A;B;C
1;2,300;3
4;5.5;6

parsedCsv中产生以下数据结构

您可以看到,如果您的文件包含列标题,则数据从行索引 1 开始,否则(没有列标题)以行索引 0。

Updated Stackblitz Example

注意:在 Stackblitz 上,我添加了以下几行,以便您查看数组是如何填充的:

  // demo output as alert
  var output: string="";
  csv.forEach(row => {
    output += "\n";
    var colNo = 0;
    row.forEach(col => {
      if (colNo>0) output += " | ";
      output += col;
      colNo++;
    });
  });
  alert(output);

【讨论】:

  • 感谢您的帮助。但是我在 onFileLoad 函数中遇到了一个问题:当我在外部类中传入一个方法时,调试器说“this”绑定到 FileReader 类...
  • @user545871 - 你能把你遇到的问题作为 stackblitz 的例子吗?这样更容易理解和解决它。
【解决方案3】:
csv2Array(fileInput: any){
//read file from input
this.fileReaded = fileInput.target.files[0];

let reader: FileReader = new FileReader();
reader.readAsText(this.fileReaded);

reader.onload = (e) => {
  let csv: string = reader.result;
  let allTextLines = csv.split(/\r|\n|\r/);
  let headers = allTextLines[0].split(',');
  let lines = [];

  for (let i = 0; i < allTextLines.length; i++) {
    // split content based on comma
    let data = allTextLines[i].split(',');
    if (data.length === headers.length) {
      let tarr = [];
      for (let j = 0; j < headers.length; j++) {
        tarr.push(data[j]);
      }

      // log each row to see output 
      console.log(tarr);
      lines.push(tarr);
    }
  }
  // all rows in the csv file 
  console.log(">>>>>>>>>>>>>>>>>", lines);
} }

【讨论】:

  • ty 为例。 csv.split(/\r|\n|\r/);从我的 csv 文件中使每一行都有一个额外的空值。我还看到 split(',') 会给我带来麻烦,因为我在欧洲,我们在 Excel 文件中为浮点数写了 19,456。这个问题可以通过在它前面加上对应的 replace(",",".") 来解决。
  • 处理错误类型'string | ArrayBuffer' 不可分配给类型 'string' ..... 进行类型转换 const csv: string = reader.result as string;
【解决方案4】:

我找到了一种提取文本的方法:

    var fr = new FileReader();
    fr.onload = function(e) {
      var text = fr.result;
      console.log(text);
    };
    fr.readAsText(files[0]);

然后使用将单独的行和单元格拆分为数组:

var rows = text.split("\n");
console.log("Row 0 " + rows[0]);
console.log("Row 1 " + rows[1]);
console.log("Row 2 " + rows[2]);
var row1 = rows[0].split(";");
console.log("Value 0,0 " + row1[0]);
console.log("Value 0,1 " + row1[1]);
console.log("Value 0,2 " + row1[2]);

*如果单元格包含“;”,此代码将无法正常工作字符,这不是我的应用程序的情况。

【讨论】:

    【解决方案5】:

    我写了一个函数作为 Promise

      /**
       * Returns the CSV file content as a string.
       * New lines are separated by '\n' inside the string.
       * @param file 
       */
      public async readCSVFile(file: File): Promise<string | ArrayBuffer> {
        return new Promise<string | ArrayBuffer>((resolve, reject) => {
          const reader = new FileReader();
    
          reader.onload = e => {
            return resolve((e.target as FileReader).result);
          };
          reader.onerror = e => {
            console.error(`FileReader failed on file ${file.name}.`);
            return reject(null);
          };
    
          if (!file) {
            console.error('No file to read.');
            return reject(null);
          }
          reader.readAsText(file);
        });
      }
    

    你可以这样使用它

    this.readCSVFile(myCsvFile).then((fileContents) => {
          //fileContents --> CSV file content as a string
     });
    

    而且,如果你正在与像ñ这样的西班牙字符打架,这对我有用

    reader.readAsText(file, 'ISO-8859-3');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-23
      • 1970-01-01
      • 2022-01-25
      • 2011-11-02
      相关资源
      最近更新 更多