How to read a local file in javascript

Started by
10 comments, last by 8Observer8 4 years, 9 months ago

I want to read a text file that's already in the project folder, but I don't know how.  I don't need files from the client, I just need files from the project folder.

I am an indie game developer who enjoys pixel art games.

Advertisement

I use the method that I read in the book: WebGL Programming Guide Authors describe in the Appendix F "Load Shader Programs from Files" how to load text files (GLSL shaders) from the project folder. You can run the JavaScript example in JSFiddle: https://jsfiddle.net/8Observer8/wdn9ubhj/

I wrote a simple example in TypeScript. You can run it in playground by click. My example just get text from here: https://www.w3.org/TR/PNG/iso_8859-1.txt and put it on the page.

Playground

Spoiler

 

Program.ts



import { TextLoader } from "./TextLoader";

class Program
{
    public static Main(): void
    {
        let filePath = "https://www.w3.org/TR/PNG/iso_8859-1.txt";

        TextLoader.Load(filePath, this.OnLoadFile);
    }

    public static OnLoadFile(fileContent: string): void
    {
        let output = document.getElementById("output");
        output.textContent = fileContent;
    }
}

// Debug Version
Program.Main();

// Release Version
// window.onload = () => Program.Main();

TextLoader.ts




export class TextLoader
{
    public static Load(filePath: string, callback: (fileContent: string) => void): void
    {
        let request = new XMLHttpRequest();

        request.onreadystatechange = () =>
        {
            if (request.readyState === 4 && request.status !== 404)
            {
                callback(request.responseText);
            }
        };

        request.open("GET", filePath, true);
        request.send();
    }
}

 

 

You can also use the FileReader API, see here for an example: https://www.javascripture.com/FileReader
(Note: this example only accepts images but can be made to read any file)

Thank you for information. I did not know about FileReader. I read about Blob and File. Could you show an example how to read a text from this .txt file: https://www.w3.org/TR/PNG/iso_8859-1.txt

The readAsText() method can get the Blob or File instances. I can get the File instance from the FileList that is returned by files[0]:


        let input = document.createElement("input") as HTMLInputElement;
        let file = input.files[0];

But how to create the File instance without the HTML input element? I tried to google but I see examples with the HTML input element.

My current code:


    public static LoadUsingFileReader(
        filePath: string, callback: (fileContent: string) => void): void
    {
        let reader = new FileReader();

        reader.onload = () =>
        {
            callback(reader.result as string);
        }
        
        let input = document.createElement("input") as HTMLInputElement;
        let file = input.files[0];

        reader.readAsText(file);
    }

 

Frankly, I'm not sure if you can create a FileList object without an input element, the documentation does not mention it. My guess is it's not allowed to prevent malicious apps from loading local data without the users' consent.

Hope this helps.

I think the FileReader instance can be used only with an input element. If you want to load local data from the server you need to use the XMLHttpRequest instance. Am I right?

This code works if you need to load data from project folder and remote server:


    public static LoadUsingXMLHttpRequest(
        filePath: string, callback: (fileContent: string) => void): void
    {
        let request = new XMLHttpRequest();

        request.onreadystatechange = () =>
        {
            if (request.readyState === 4 && request.status !== 404)
            {
                callback(request.responseText);
            }
        };

        request.open("GET", filePath, true);
        request.send();
    }

 

HTTPRequest should work, however Chrome for example will not allow you to load any local data at all, except when running a HTTP server.

I think, we have two different situations:

  1. The program allows to user to load files from his computer (from his hard driver) by click on the "Choose" button. In this case you need to use FileReader 
  2. We have some text files in our project folder, for example, levels for our game in text format, OBJ file for 3D models, shader files and so on. And we have to load them from the HTTP server. In this case you need to use XMLHttpRequest

We need some information from topic starter to understand what he wants.

I realised these two situations (XMLHttpRequest and FileReader) in TypeScript.

Playground

Source Code on GitHub

Source Code:

Spoiler

index.html



<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    
    <title>Text File Loader in TypeScript</title>

    <!-- Debug Version -->
    <script data-main="js/RequireConfig" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>

    <!-- Release Version -->
    <!-- <script src="js/bundle.min.js"></script> -->
</head>

<body>
    <input id="input" type="file" accept=".txt">
    <pre><span id="output"></span></pre>
</body>

</html>

Program.ts



import { TextLoader } from "./TextLoader";

// Playground: https://next.plnkr.co/edit/JgPIlgBpNQK8BwO2?preview

class Program
{
    public static Main(): void
    {
        // FileReader
        let inputElement = document.getElementById("input") as HTMLInputElement;
        if (inputElement === null)
        {
            console.log("Failed to get the \"input\" element.");
            return;
        }
        inputElement.onchange = (ev: Event) =>
        {
            TextLoader.LoadUsingFileReader(inputElement, this.OnLoadFile);
        };

        // XMLHTTPRequest
        let filePath = "https://www.w3.org/TR/PNG/iso_8859-1.txt";
        TextLoader.LoadUsingXMLHttpRequest(filePath, this.OnLoadFile);
    }

    public static OnLoadFile(fileContent: string): void
    {
        let output = document.getElementById("output");
        output.textContent = fileContent;
    }
}

// Debug Version
Program.Main();

// Release Version
// window.onload = () => Program.Main();

RequireConfig.ts



requirejs.config({
    baseUrl: "js"
});

requirejs(["Program"], (Program) => { });

TextLoader.ts




export class TextLoader
{
    public static LoadUsingXMLHttpRequest(
        filePath: string, callback: (fileContent: string) => void): void
    {
        let request = new XMLHttpRequest();

        request.onreadystatechange = () =>
        {
            if (request.readyState === 4 && request.status !== 404)
            {
                callback(request.responseText);
            }
        };

        request.open("GET", filePath, true);
        request.send();
    }

    public static LoadUsingFileReader(
        input: HTMLInputElement,
        callback: (fileContent: string) => void): void
    {
        let reader = new FileReader();

        reader.onload = () =>
        {
            callback(reader.result as string);
        }

        let file = input.files[0];
        reader.readAsText(file);
    }
}

package.json



{
    "name": "text-file-loader_typescript",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "build-debug": "tsc -p tsconfig.debug.json",
        "compile-release": "tsc -p tsconfig.release.json",
        "bundle-release": "browserify public/js/Program.js -o public/js/bundle.js",
        "minify-release": "uglifyjs public/js/bundle.js -o public/js/bundle.min.js",
        "build-release": "npm run compile-release && npm run bundle-release && npm run minify-release"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "@types/requirejs": "^2.1.31"
    }
}

tsconfig.debug.json



{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "sourceMap": true
    }
}

tsconfig.json



{
    "compilerOptions": {
        "target": "es5",
        "module": "amd",
        "sourceMap": false,
        "outDir": "public/js"
    },
    "include": [
        "src/**/*.ts"
    ]
}

tsconfig.release.json



{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "module": "commonjs"
    }
}

launch.json



{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "chrome",
            "request": "launch",
            "name": "Launch Client",
            "url": "http://localhost:8080",
            "webRoot": "${workspaceFolder}/public"
        }
    ]
}

 

 

This topic is closed to new replies.

Advertisement