Writing UTF8 text to file - javascript

I am using the following function to save text to a file (on IE-8 w/ActiveX).
function saveFile(strFullPath, strContent)
{
var fso = new ActiveXObject( "Scripting.FileSystemObject" );
var flOutput = fso.CreateTextFile( strFullPath, true ); //true for overwrite
flOutput.Write( strContent );
flOutput.Close();
}
The code works fine if the text is fully Latin-9 but when the text contains even a single UTF-8 encoded character, the write fails.
The ActiveX FileSystemObject does not support UTF-8, it seems. I tried UTF-16 encoding the text first but the result was garbled. What is a workaround?

Try this:
function saveFile(strFullPath, strContent) {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var utf8Enc = new ActiveXObject("Utf8Lib.Utf8Enc");
var flOutput = fso.CreateTextFile(strFullPath, true); //true for overwrite
flOutput.BinaryWrite(utf8Enc.UnicodeToUtf8(strContent));
flOutput.Close();
}

The CreateTextFile method has a third parameter which decides whether file be written unicode or not. You can do like:
var flOutput = fso.CreateTextFile(strFullPath,true, true);
Interestingly, way back I had created this little script to save files in unicode format:
Set FSO=CreateObject("Scripting.FileSystemObject")
Value = InputBox ("Enter the path of the file you want to save in Unicode format.")
If Len(Trim(Value)) > 0 Then
If FSO.FileExists(Value) Then
Set iFile = FSO.OpenTextFile (Value)
Data = iFile.ReadAll
iFile.Close
Set oFile = FSO.CreateTextFile (FSO.GetParentFolderName(Value) & "\Unicode" & GetExtention(Value),True,True)
oFile.Write Data
oFile.Close
If FSO.FileExists (FSO.GetParentFolderName(Value) & "\Unicode" & GetExtention(Value)) Then
MsgBox "File successfully saved to:" & vbCrLf & vbCrLf & FSO.GetParentFolderName(Value) & "\Unicode" & GetExtention(Value),vbInformation
Else
MsgBox "Unknown error was encountered!",vbCritical
End If
Else
MsgBox "Make sure that you have entered the correct file path.",vbExclamation
End If
End If
Set iFile = Nothing
Set oFile= Nothing
Set FSO= Nothing
Function GetExtention (Path)
GetExtention = Right(Path,4)
End Function
Note: This is VBScript code, you should save that code in a file like unicode.vbs, and once you double click that file, it will run.

Add a third parameter, true, in your call to the CreateTextFile method. See this page.

function saveFile(strFullPath, strContent) {
var fso = new ActiveXObject( "Scripting.FileSystemObject" );
var flOutput = fso.CreateTextFile( strFullPath, true, true ); //true for overwrite // true for unicode
flOutput.Write( strContent );
flOutput.Close();
}
object.CreateTextFile(filename[, overwrite[, unicode]])

Related

Text with line breaks returns \r\n in text through Ajax/JavaScript

Code that works fine except for the issue of passing a value back and forth between JavaScript, Ajax, and PHP. Using TinyMCE as the editor, when I add a paragraph break in the text, save the data (passing it through JavaScript/Ajax and PHP to do so) the text appears to be okay. Here's the JavaScript and Ajax code -- this works, it passes the data correctly to the PHP program when the submit button is clicked:
// save the main who's who form data:
$("form#who_main").submit(function(e)
{
e.preventDefault();
// first thing, clear out the message div used for this (if there's anything there):
document.getElementById("who_message").innerHTML = "";
// because we're using TinyMCE, need to replace value in that into the textarea
// so that when JavaScript gathers the formData it is getting it from the textarea
// controls (it doesn't know what to do with TinyMCE):
var shortbio = tinymce.get('shortbio').getContent();
document.getElementById( "shortbio" ).value = shortbio;
var user_notes = tinymce.get('user_notes').getContent();
document.getElementById( "user_notes" ).value = user_notes;
var admin_notes = tinymce.get('admin_notes').getContent();
document.getElementById( "admin_notes" ).value = admin_notes;
// this loads all the controls of the form rather than doing one at a time and fumbling
// with the file object ...:
var formData = new FormData(this);
// ajax call to attempt to upload and save the image:
$.ajax
({
type: "POST",
url: "<?php echo $History_html_RootPath; ?>admin/AjaxCalls/who_update_main_save.php",
data: formData,
dataType: "json", // return value is json array
processData : false,
contentType: false,
success: function(data)
{
// need to see if we have an error, if so, display it, otherwise,
// we should hopefully have success ...
if ( data[0].toLowerCase().includes( "error" ) )
{
var errormsg = "<div class='alert alert-danger'>"+data+"</div>";
document.getElementById("who_message").innerHTML = errormsg;
return;
}
else
{
// success!
// update things on screen, so we don't get confused using the data array returned
// from PHP:
document.getElementById("namecode").value = data[0];
document.getElementById("region").value = data[1];
document.getElementById("local").value = data[2];
document.getElementById("preferredtitle").value = data[3];
document.getElementById("shortbio").value = data[4];
tinymce.get('shortbio').setContent( data[4] );
document.getElementById("headshotphoto").value = data[5];
document.getElementById("photographername").value = data[6];
document.getElementById("photographerlink").value = data[7];
document.getElementById("user_notes").value = data[8];
tinymce.get('user_notes').setContent( data[8] );
document.getElementById("admin_notes").value = data[9];
tinymce.get('admin_notes').setContent( data[9] );
// clear out the upload file control:
//document.getElementById("headshotphoto").value = "";
// change the message:
var message = "<div class='alert alert-success'>";
message += "<b>Success!</b> This data has been updated in the <i>holding</i> table.";
message += "</div>";
document.getElementById("who_message").innerHTML = message;
return;
}
} // end success
}); // end ajax call
}) // end of code associated with who_main submit
The PHP file receives the data via post, and I use the PHP function mysqli_real_escape_string() to deal with issues. The one problem with doing this is that it appears to insert backslashes for quotes (single and double), and so on. I just had a thought that might be the cause of the problem, and that is the use of this function, I am not sure. I will test it, but in the meantime. ... I save the data to the table and all is good. If there's a paragraph break, the proper tags are saved out into the table.
<p>Some text</p><p>More text 'quoted text'</p>
When I pass the data back using JSON encoding:
$returndata = array();
$returndata[0] = $namecode;
$returndata[1] = $region;
$returndata[2] = $local;
$returndata[3] = $preferredtitle;
$returndata[4] = $shortbio;
$returndata[5] = $photo_file;
$returndata[6] = $photographername;
$returndata[7] = $photographerlink;
$returndata[8] = $user_notes;
$returndata[9] = $admin_notes;
// done-done:
echo json_encode( $returndata );
return;
The code above (the javascript/Ajax code) comes back looking like:
<p>Some text</p>\r\n<p>More text \'quoted text\'</p>
I need to not have the \r\n and \' (or \") showing up in my text. If I were to save it again like that it gets weirder as the backslashes get duplicated and more. I am sure there's some thing I am missing, but I don't know what it is. This is making me crazy because everything else works exactly as I need it to.
NOTE Added code that I have attempted to use, in PHP, to deal with "escapes", it works for single and double quotes, but not for the \r\n characters -- instead it just strips out the backslash:
function remove_escapes( $string )
{
$string = str_replace ( "\'", "'", $string ); // convert single quote
$string = str_replace ( "\"", """, $string ); // convert double-quote
$string = str_replace ( "\r\n", "", $string ); // remove \r\n
$string = str_replace ( "\\", "", $string ); // remove slash
// anything else giving us heartburn?
return $string;
} // eof: remove_escapes()
If I use this with the json array, I get the letters rn inserted between paragraphs:
$returndata[8] = remove_escapes( $user_notes );
$returndata[9] = remove_escapes( $admin_notes );
maybe doing something like data.replace(/\n/g, '<br>') this will replace all newline markers with the html newline or data.replace(/\\n/g, '<br>') to look for the characters rather than a newline marker
I have done some testing to examine the data and it appears to be happening because of the mysqli_real_escape_string() function when I get the data from the $_POST() array. If I take that out, I am not getting the \r\n codes. So perhaps the jquery post is passing things in a way I don't need that function? Further testing on the three different text controls shows it working without the need to use mysqli_real_escape_string, and I have some extra functionality to deal with looking for JavaScript and such in the text, so I may be able to simplify the code. Unless someone can tell me a reason not to do this ...?
The mysqli_real_escape_string() is there so that special characters are escaped, this helps prevent hacking attacks like sql injection.
It appears that the only solution I can find is to continue with mysqli_real_escape_string(), but when passing the information back, after saving the changes, re-load the data from the table, which does not display the escape characters and therefore avoids the issue. It seems like a lot of extra data processing, but it's only ever (in my code) one row at a time that is being passed back and forth.

javascript, how could we read a local text file with accent letters into it?

I have one doubt because I need to read a local file and I have been studying some threads, and I have seen various ways to handle it, in most of the cases there is an input file.
I would need to load it directly through code.
I have studied this thread:
How to read a local text file?
And I could read it.
The surprising part was when I tried to split the lines and words, it showed: � replacing accent letters.
The code I have right now is:
myFileReader.js
function readTextFile(file) {
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function () {
if (rawFile.readyState === 4) {
if (rawFile.status === 200 || rawFile.status == 0) {
allText = rawFile.responseText;
console.log('The complete text is', allText);
let lineArr = intoLines(allText);
let firstLineWords = intoWords(lineArr[0]);
let secondLineWords = intoWords(lineArr[1]);
console.log('Our first line is: ', lineArr[0]);
let atlas = {};
for (let i = 0; i < firstLineWords.length; i++) {
console.log(`Our ${i} word in the first line is : ${firstLineWords[i]}`);
console.log(`Our ${i} word in the SECOND line is : ${secondLineWords[i]}`);
atlas[firstLineWords[i]] = secondLineWords[i];
}
console.log('The atlas is: ', atlas);
let atlasJson = JSON.stringify(atlas);
console.log('Atlas as json is: ', atlasJson);
download(atlasJson, 'atlasJson.txt', 'text/plain');
}
}
};
rawFile.send(null);
}
function download(text, name, type) {
var a = document.getElementById("a");
var file = new Blob([text], {type: type});
a.href = URL.createObjectURL(file);
a.download = name;
}
function intoLines(text) {
// splitting all text data into array "\n" is splitting data from each new line
//and saving each new line as each element*
var lineArr = text.split('\n');
//just to check if it works output lineArr[index] as below
return lineArr;
}
function intoWords(lines) {
var wordsArr = lines.split('" "');
return wordsArr;
}
The doubt is: how could we handle those special character which are the vowels with accent?
I ask this, because even in the IDE thet interrogation marks appeared if we load the txt in UTF-8, so then I changed to ISO-8859-1 and it loaded well.
Also I have studied:
Read UTF-8 special chars from external file using Javascript
Convert special characters to HTML in Javascript
Reading a local text file from a local javascript file?
In addition, could you explain if there is a shorter way to load files in client javascript. For example in Java there is the FileReader / FileWriter / BufferedWriter. Is theren in Javascript something similar?
Thank you for you help!
It sounds like the file is encoded with ISO-8859-1 (or possibly the very-similar Windows-1252).
There's no BOM or equivalent for those encodings.
The only solutions I can see are:
Use a (local) server and have it return the HTTP Content-Type header with the encoding identified as a charset, e.g. Content-Type: text/plain; encoding=ISO-8859-1
Use UTF-8 instead (e.g., open the file in an editor as ISO-8859-1, then save it as UTF-8 instead), as that's the default encoding for XHR response bodies.
Put your text in an .html file with the corresponding content type,
for example:
<meta http-equiv="Content-Type" content="text/html; charset="UTF-8">
enclose the text between two tags ("####" in my example) (or put in a div)
Read the html page, extract the content and select the text:
window.open(url); //..
var content = newWindow.document.body.innerHTML;
var strSep="####";
var x = content.indexOf(strSep);
x=x+strSep.length;
var y = content.lastIndexOf(strSep);
var points=content.slice(x, y);

From .txt data give values to inputs

I'm trying to fill some inputs when you load a page, using the data I have from a .txt file. This file has a list of numbers
1
2
3
Something like this. So I wanted to read this lines and put them in their corresponding input. Suggestions on how to do this??
I tried with this code, but maybe I have a mistake that I don't know about, I'm starting with javascript.
function loadvalues()
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var s = fso.OpenTextFile("E://Steelplanner/Demand_Routing/Pruebas/OrderBalancing_Masivos/ModificaFechaTope/DueDate/Datosactuales.txt", true);
var Ia5 = document.getElementById("Ia5sem");
var text = s.ReadLine();
Ia5.value = text;
Try using file.ReadLine() until document not completely read using while loop with AtEndOfStream of file variable.
Here is example you can refer: ReadLine Method
Don't forget to replace TextFile path to your own text file path
My text file contains same data as in your example
<script type="text/javascript">
var fso = new ActiveXObject("Scripting.FileSystemObject");
//specify the local path to Open and always add escape character else throw error for bad file name
var file = fso.OpenTextFile("C:\\Users\\MY_USER\\Desktop\\txtfile.txt", 1);
var Ia5 = document.getElementById("Ia5sem");
while (!file.AtEndOfStream) {
var r = file.ReadLine();
Ia5.innerHTML = Ia5.innerHTML + ("<br />" + r);
}
file.Close();
</script>
<p id="Ia5sem">HI</p>
So, I don't know why, but I just changed the name of the variables and made a slight change in the .OpenTextFile line and it worked.
function loadvalues()
{
var file = new ActiveXObject("Scripting.FileSystemObject");
var text = file.OpenTextFile("E:\\Steelplanner\\Demand_Routing\\Pruebas\\OrderBalancing_Masivos\\ModificaFechaTope\\DueDate\\Datosactuales.txt", 1,false);
var Ia5s = document.getElementById("Ia5sem");
Ia5s.value = text.ReadLine();
var Ia4s = document.getElementById("Ia4sem");
Ia4s.value = text.ReadLine();
text.close();
}
Anyways, I'm gonna check the FileReader() for future references and the script #Sarjan gave, maybe I can improve it, but I have other things to finish. Thanks for everything.

Check file extension with regex - application/vnd.ms-excel

I need to check if a file is a xls. I am trying this code, but I upload a xls file and I am getting the error Invalid file.
var acceptFileTypes = /(.|\/)(application\/vnd.ms-excel)$/i;
console.log(data.originalFiles[0]['type']); //application/vnd.ms-excel
if (!acceptFileTypes.test(data.originalFiles[0]['type'])) {
uploadErrors.push('Invalid file');
}
There is something wrong with the regex?
Here's your error: (.|\/)
This part needs to consume one character - it is actually equivalent to ..
Remove that part and you'll be fine. You also need to escape the periods:
var acceptFileTypes = /application\/vnd\.ms-excel$/i;
Of course, this is equivalent to:
var acceptFileTypes = "application/vnd.ms-excel";
var isExcel = yourFile.toLowerCase().indexOf(acceptFileTypes, yourFile.length - acceptFileTypes.length) == 0;

unable to read the full content of the file in javascript

I have this piece of javascript code
var file = Components.classes["#mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
file.initWithPath( this.savefile );
if ( file.exists() == false ) {
return null;
}
var is = Components.classes["#mozilla.org/network/file-input-stream;1"]
.createInstance( Components.interfaces.nsIFileInputStream );
is.init( file,0x01, 00004, null);
var sis = Components.classes["#mozilla.org/scriptableinputstream;1"]
.createInstance( Components.interfaces.nsIScriptableInputStream );
sis.init( is );
output = sis.read( sis.available() );
sis.close();
is.close();
this.filterData = output;
return output;
Actually the file that i am reading is a binary file and has lets say 350 bytes.
Now the 19 byte is "zero", so what happens is in the above code i get only 18 bytes in output.
when i tried debugging sis.available does return 350. But sis.read only reads upto Zero byte.
I want the way to read whole of 350 bytes in output.
EDIT
See https://developer.mozilla.org/en-US/docs/Reading_textual_data
Quote:
var charset = /* Need to find out what the character encoding is. Using UTF-8 for this example: */ "UTF-8";
var is = Components.classes["#mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
// This assumes that fis is the nsIInputStream you want to read from
is.init(fis, charset, 1024, 0xFFFD);
is.QueryInterface(Components.interfaces.nsIUnicharLineInputStream);
if (is instanceof Components.interfaces.nsIUnicharLineInputStream) {
var line = {};
var cont;
do {
cont = is.readLine(line);
// Now you can do something with line.value
} while (cont);
}
This avoids the null byte problems, is unicode safe, and works with less esoteric object types.
Original:
As per my comment above, and in light of your edit,
See https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIScriptableInputStream where read() comes with the warning: If the data contains a null byte, then this method will return a truncated string. You may want to use readBytes() instead.
Alternatively, here's another way to do it:
var ph = Components.classes["#mozilla.org/network/protocol;1?name=file"]
.createInstance(Components.interfaces.nsIFileProtocolHandler);
var file_to_read = ph.getURLSpecFromFile(file);
var req = new XMLHttpRequest();
req.onerror = function(e) {
onError(e);
}
req.onreadystatechange = function() {
if (log.readyState == 4) {
//...
}
}
req.open("GET", file_to_read, true);
I may be wrong, but have you tried sending a simple GET request? In AJAX? Or do you strictly want to use JS?
EDIT:
Refer to this - How do I load the contents of a text file into a javascript variable?

Categories