21

I've created a simple HTML page that takes some input from the user to store on a server to be retrieved later -- this is how the text is treated when the user clicks a submit button (I've placed numbered comments under the key lines but provide the surrounding code for context):

var origText = $('#input-field').val(),
        // 1. GETS WHATEVER USER TYPED INTO INPUT FIELD
    jsonText = '{ "text": "' + origText + '" }',
        // 2. WRAPS IT AN OBJECT STRING
    ajaxText = encodeURIComponent(jsonText);
        // 3. ENCODES THE STRING FOR USE WITH AJAX

$.ajax({
    url: 'http://localhost:8124/',
    data: 'save=' + ajaxText + '&fn=save',
        // 4. THE ENCODED STRING IS ADDED TO THE QUERY SECTION OF THE AJAX REQUEST
    dataType: "jsonp",
    cache: false,
    timeout: 5000,
    success: function(data) {
        $("#input-ready").html(data.save.text);
    },
    error: function(jqXHR, textStatus, errorThrown) {
        alert('error ' + textStatus + " " + errorThrown);
    }
});

The request is sent to a NodeJS server I am running locally, which (within the http.createServer callback) does the following:

var queryObj = url.parse(req.url, true).query;
    // 1. GET THE QUERY PART OF THE REQUEST/URL AS AN OBJECT
res.writeHead(200, {'Content-Type': 'application/javascript'});
    // 2. PREPARE SERVER'S RESPONSE AS JAVASCRIPT
queryObj.fn = queryObj.fn || '';
queryObj.save = queryObj.save || '';
queryObj.callback = queryObj.callback || '';
    // 3. ENSURE THE PROPERTIES NEEDED ARE DEFINED, EVEN IF FALSE-Y
if (queryObj.fn === 'save') {
    // 4. IF THE REQUEST IS TO SAVE THEN WRITE THE USER INPUT AS OBJECT TO A TEXT FILE
    fs.writeFile('jsonp-storage-2.txt', queryObj.save, function (err) {
        if (err) {
            throw err;
        } else {
            console.log('Saved message successfully.', 'Ready to be read now.');
            res.end(queryObj.callback +
                '({ fn: "' + queryObj.fn + '", save: ' + queryObj.save + ' })');
        }
    });
}

Assuming the user types and submits "this is a line of text", the output on the server is a text file called jsonp-storage-2.txt containing this:

{ "text": "this is a line of text" }

After all that, my question is quite simple. How do I prettify the output in the text file?

The code needs work but I'm thinking of using this to try storing larger objects for reading later. However, at the server end, I would like the files (for now) to be easy for me to read when opening them with Notepad, for example.

I have tried using \n and \t like so:

jsonText = '{\n\t"text": "' + origText + '"\n}',

I've also tried \r. But the lines remain unbroken.

Some answers suggest that I can only do this at the level of the encoded string or after the file has been written. Perhaps I missed something simple. Is there a way to do it by manipulating my jsonText variable?

UPDATE:

Just to be clearer about the output desired -- currently the content of the text file produced looks like this:

{ "text": "this is a line of text" }

But I'd like to know if it can be produced like this:

{
    "text": "this is a line of text"
}
Community
  • 1
  • 1
guypursey
  • 3,114
  • 3
  • 24
  • 42
  • Is it really important that you store them prettified? Why not just beautify them when, and if, you actually open them? – Dave Newton Jan 05 '13 at 15:19
  • As the white-lines are part of your storage concept, and not as much part of the message, why not just append them in your nodeJS code? fs.writeFile('jsonp-storage-2.txt', queryObj.save + "\n\n", function (err) { – Roonaan Jan 05 '13 at 15:22
  • @DaveNewton Thanks for the comment. I'm not yet sure how many such files I want to produce. I realise it probably seems like too trivial process to bother automating at this small scale, but I'm curious as to whether it can be done as I wouldn't want to have to open every file and manually beautify each one. Even if it only took one click when the file was open, it would get tedious if there were a hundred or more. – guypursey Jan 05 '13 at 15:29
  • @guypursey That's why they invented scripting; don't know why anybody would do it manually. But why are you opening all those files anyway? That aside: is it possible the JSON is being parsed on the Node side and stored as JSON, within which such whitespace is meaningless? – Dave Newton Jan 05 '13 at 15:35
  • Thanks @Roonaan. That might work but, in order to properly prettify the output, the line breaks and indents would need to fall within the string itself (rather than an append). I've edited my question to make it clearer. – guypursey Jan 05 '13 at 15:38
  • @DaveNewton Good question! This code is a small part of a bigger project I'm working on and in order to test the rest of the code I'd like to be able to examine each file to see the output with as little mediation as possible. But I need to know how much I can do with this code first to get the files produced as near to human-readable format as I can. – guypursey Jan 05 '13 at 15:47
  • @DaveNewton What you mention about JSON being parsed on the Node side could be the cause. I'll look into that. Thanks. (Meant to put this at the end of my last comment but hit return and it submitted; sorry.) – guypursey Jan 05 '13 at 15:49
  • @guypursey Be aware that "looking at the file" is only barely testing; if you really want to test, test by parsing the file as JSON and accessing it that way. – Dave Newton Jan 05 '13 at 15:50
  • @DaveNewton Thanks for the advice. I suspect I would have come to a point where I realised parsing the file would be more beneficial for rigorous testing but I'll be extra-conscious of it now. – guypursey Jan 05 '13 at 16:11

2 Answers2

39

Use

var os = require('os');
var jsonText = '{' + os.EOL + '\t"text": "' + origText + '"' + os.EOL + '}';
  • This answer must be the correct one. Because writing windows 'return caret character' \r might throw an exception in some cases. Be very careful with that! – Soul_man Apr 11 '14 at 05:25
  • 1
    Sorry, I've only just seen this. It's a better answer than mine so I've marked it correct. – guypursey Jan 19 '15 at 17:38
  • 4
    You can also use ```JSON.stringify(data, null, " ")``` – vrunoa Sep 26 '15 at 18:44
9

It turns out that when writing a string to a (text) file with Node.js [EDIT: in Windows], use \r\n for a new line.

As with encoded line breaks, both a return carriage and a new line is necessary. So the line of code needed to be this rather than having just \r or just \n:

jsonText = '{\r\n\t"text": "' + origText + '"\r\n}',

The resulting file's content now displays as desired:

{
    "text": "this is a line of text"
}
Community
  • 1
  • 1
guypursey
  • 3,114
  • 3
  • 24
  • 42
  • 4
    Newline encoding varies by platform. `\r\n` is the newline encoding for Windows and related platforms, and `\n` is the newline encoding for UNIX related platforms. See http://en.wikipedia.org/wiki/Newline for a historical diversion. – Plynx Feb 26 '13 at 11:00
  • @Plynx Thanks. I should have replied to this comment a while ago, and am doing so now to encourage people to the platform-related answer which I have marked correct. My answer here was a result of using Node.js for Windows when I was starting out (so it worked for me, hence its being left here) but is not appropriate for all uses. – guypursey Jun 25 '15 at 07:30