Jump to content
  • Advertisement
Pepsidog

How to read a local file in javascript

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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();
    }
}

 

 

Share this post


Link to post
Share on other sites
Posted (edited)

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);
    }

 

Edited by 8Observer8

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
Posted (edited)

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();
    }

 

Edited by 8Observer8

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
Posted (edited)

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.

Edited by 8Observer8

Share this post


Link to post
Share on other sites
Posted (edited)

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"
        }
    ]
}

 

 

Edited by 8Observer8

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!