When the FileReader reads the file as readAsArrayBuffer, it ensures that the correct encoding is used

Currently, I am developing a script in JavaScript to read uploaded .csv/.xlsx files and convert the data into an array containing each row. Using FileReader along with SheetJs, I have successfully managed to achieve this by implementing the following code:

//Code for the new excel reader
$scope.do_file =  function(files)
{
    $scope.fileContent  = [];
    var X = XLSX;
    var global_wb;
    var f = files[0];
    var reader = new FileReader();
    reader.onload = function(e)
    {
        var data = e.target.result;console.log(data);
        global_wb = X.read(data, {type: 'array'});
        var output = "";
        var result = {};
        global_wb.SheetNames.forEach(function(sheetName) {
            var roa = X.utils.sheet_to_json(global_wb.Sheets[sheetName], {header:1});
            if(roa.length) result[sheetName] = roa;
        });
        $scope.fileContent =  result["Sheet1"];
        if(!result["Sheet1"])
        {
            $scope.fileContent =  result["contacts"].filter(function(el) { return typeof el != "object" || Array.isArray(el) || Object.keys(el).length > 0; });
        }
    };
    reader.readAsArrayBuffer(f);
};

The above code works well for most files, but encounters difficulty when processing a file with Hebrew text encoded in Windows-1255, resulting in corrupted data.

To explore alternative solutions, I attempted to read the file as text using reader.readAsText and adjust the encoding accordingly. Here is the revised code snippet:

function is_Hebrew(data)
{
    var position = data.search(/[\u0590-\u05FF]/);
    return position >= 0;
}

$scope.do_file =  function(files)
{
    var fullResult = [];
    var file = files[0];
    var reader = new FileReader();
    reader.onload = function(e){
        var data = e.target.result;
        if(!is_Hebrew(data.toString()))
        {
          reader.readAsText(file,'ISO-8859-8');   
        }
    };
    reader.readAsText(file);
    reader.onloadend = function(){
        var lines = reader.result.split('\r\n');
        console.log(lines);
        lines.forEach(element => {
            var cell = element.split(',');
            fullResult.push(cell);
        });

         console.log(reader);
    };
};

However, the modified code fails to accurately interpret the file as it does not distinguish between rows and cells. In instances where a cell contains a string with comma-separated values (e.g. "25,28,29"), the array output becomes inaccurate, treating each value as a separate cell.

Therefore, I have opted to continue using the initial method, but encounter difficulties in changing the encoding. Is there a way to modify the encoding in the original code that utilizes readAsArrayBuffer to extract the file data?

Answer №1

Through extensive exploration of potential solutions, I discovered that the most effective approach to the given question was to merge the two methods mentioned above. The first method is used for reading xlsx files, while the second method is employed for reading csv files. Additionally, a supplemental javaScript library called papaparse is utilized in the second method to address data reading challenges at the cell level.

$scope.is_Hebrew = function($data){
var position = $data.search(/[\u0590-\u05FF]/);
return position >= 0;
}

// Implementation for the new excel reader
$scope.do_file =  function(files)
{
    var config = {
    delimiter: "",  
    newline: "",    
    quoteChar: '"',
    escapeChar: '"',
    header: false,
    trimHeader: false,
    dynamicTyping: false,
    preview: 0,
    encoding: "",
    worker: false,
    comments: false,
    step: undefined,
    complete: undefined,
    error: undefined,
    download: false,
    skipEmptyLines: false,
    chunk: undefined,
    fastMode: undefined,
    beforeFirstChunk: undefined,
    withCredentials: undefined
    };

    $scope.fileContent  = [];
    var f = files[0];
    var fileExtension = f.name.replace(/^.*\./, '');
    if(fileExtension == 'xlsx')
    {
        var X = XLSX;
        var global_wb;
        var reader = new FileReader();
        reader.onload = function(e)
        {
            var data = e.target.result;
            global_wb = X.read(data, {type: 'array'});
            var result = {};
            global_wb.SheetNames.forEach(function(sheetName) {
               var roa = X.utils.sheet_to_json(global_wb.Sheets[sheetName], {header:1});
               if(roa.length) result[sheetName] = roa;
            });
            $scope.fileContent =  result["Sheet1"];
            if(!result["Sheet1"])
            {
               $scope.fileContent =  result["contacts"].filter(function(el) { return typeof el != "object" || Array.isArray(el) || Object.keys(el).length > 0; });
            }

        };
        reader.readAsArrayBuffer(f);

    }
    else if(fileExtension == 'csv')
    {
    var reader = new FileReader();
    reader.onload = function(e)
    {
        var data = e.target.result;
        console.log(f);
        console.log($scope.is_Hebrew(data.toString()));
        if(!$scope.is_Hebrew(data.toString()))
        {
           reader.readAsText(f,'ISO-8859-8');   
        }
    };

    reader.readAsText(f);
    reader.onloadend = function(e){
        var c =  Papa.parse(reader.result,[ config])
        console.log(c);
        $scope.fileContent =  c["data"].filter(function(el) { return typeof el != "object" || Array.isArray(el) || Object.keys(el).length > 0; });

    };

    }
    else
    {
       alert("File Not supported!");
    }

$scope.fileContent.push([]);
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to dynamically load a personalized JavaScript file for individual users depending on their PHP login credentials?

Currently, I am conducting a web-based experiment in which students log into a website to take practice tests for a class. Initially, the students land on a login page that includes the following code: include_once("core/config.php"); include_once("core/ ...

Javascript eval function providing inaccurate results

I have encountered a problem while using eval() for a calculator I am developing. When I input the following code: console.log(eval("5.2-5")); The output is: 0.20000000000000018 I am confused as to why this is happening. Thank you for your assistance. ...

"Production environment encounters issues with react helper imports, whereas development environment has no trouble with

I have a JavaScript file named "globalHelper.js" which looks like this: exports.myMethod = (data) => { // method implementation here } exports.myOtherMethod = () => { ... } and so forth... When I want to use my Helper in other files, I import it ...

Highest Positioned jQuery Mobile Section

Requesting something a bit out of the ordinary, I understand. I currently have a jQueryMobile page set up with simplicity: <div data-role="page" class="type-home" id="home"> <div data-role="header" data-theme="b"> <h1>Our To ...

Are jQuery plugins offering accessible public functions?

I am currently working on enhancing the functionality of a jQuery plugin. This plugin serves as a tag system and utilizes autocomplete provided by jQuery UI. Presently, there is no direct method (aside from parsing the generated list items) to determine ...

What is the best way to extract the class name from ui.item or event using the function(event, ui)?

Is there a way in jQuery to extract the class name from a function with two parameters, event and ui? For example, consider the following code snippet: $(document).tooltip({ show: null, position: { my: "left top", at: "left bottom ...

AngularJS dropdown menu for input selection binding

Hey there, I need some help with the code below: <input type="text" class="form-controlb" ng-model="item.name" id="name" placeholder="Enter Name" /> Also, I have a dropdown as shown here: <div class="col-sm-12" ng-model="query"> ...

Access the data attribute of a button element in AngularJS

Utilizing Angularjs for managing pagination loop button id=remove_imslide, I am attempting to retrieve the value of data-img_id from the button to display in an alert message using a Jquery function on button click, but I am encountering issues. This is h ...

Tips for submitting a form textarea input from CKEditor using AJAX

I am currently utilizing CKEditor, jQuery, and the jQuery form plugin. My objective is to submit the content of the CKEditor form through an Ajax query. Below is the code I have implemented: <form id="article-form" name="article-form" method="post" act ...

The utility of commander.js demonstrated in a straightforward example: utilizing a single file argument

Many developers rely on the commander npm package for command-line parsing. I am considering using it as well due to its advanced functionality, such as commands, help, and option flags. For my initial program version, I only require commander to parse ar ...

Remove hidden data upon moving cursor over table rows after a delay

Hey there! I'm in need of a little assistance, so I hope you can lend me a hand. Here's the scenario: Within my category table, there are numerous rows, each containing a hidden textbox with an empty value and a unique ID. As users navigate t ...

Can you explain the significance of this async JavaScript server application error?

While working on a weather app website connected to another site through a server, I encountered an issue with asynchronous JavaScript. Upon running the code, I received an error message stating "uncaught syntax error: unexpected end of input" in the last ...

Is the removal of the Vue-Router link happening when you click on the top app bar icon in Google Material

Review of the following code snippet: <!DOCTYPE html> <html> <head> <title>test</title> <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='vie ...

Service in Angular2+ that broadcasts notifications to multiple components and aggregates results for evaluation

My objective is to develop a service that, when invoked, triggers an event and waits for subscribers to return data. Once all subscribers have responded to the event, the component that initiated the service call can proceed with their feedback. I explore ...

Utilizing pure JavaScript to dynamically fetch HTML and JavaScript content via AJAX, unfortunately, results in the JavaScript

I am trying to load an HTML file using AJAX and then execute a script. Here is the content of the HTML file I want to load: <div class="panel panel-body"> <h4>Personal Data</h4> <hr /> <span data-bind="editable: firs ...

Issues with MySQL not functioning properly when using Promise.All in a Node.js environment

When it comes to running multiple mysql queries asynchronously in express node.js, MySQL works well with simple callbacks. However, I wanted to take it a step further by using async await with promise.all. I also experimented with promise.allSettled, but u ...

What is the best way to incorporate tinymce into webpack?

I am facing an issue with integrating tinymce with webpack. It assigns a property called tinymce to window, so one solution is to use the following syntax to require() it (as explained in the bottom of the EXPORTING section of the webpack documentation): ...

In Angular, the process of duplicating an array by value within a foreach function is not

I have been attempting to duplicate an array within another array and make modifications as needed. this.question?.labels.forEach((element) => { element["options"] = [...this.question?.options]; // I've tried json.stringify() as wel ...

Time whizzes by too swiftly

After attempting to create an automated slideshow with clickable buttons, I encountered a problem. The slideshow functions properly, but as soon as I click one of the buttons, the slideshow speeds up significantly. This is what I implemented in my attempt ...

Using Vue's $emit method within a Promise

I am currently working on an image upload feature that is based on a Promise. Within the "then" callback, I am attempting to $emit an event named 'success'. Although my VueDevTools shows me that the success event has been triggered, the associate ...