all. I've an issue that I cannot understand why it happens.
I have to download a file that is stored in hex, so I have to read it in hex, convert it in bin and then write it on an Android/iOS device.
To reach that goal, in my React project I read the file from the machine, convert it to bin and then send it to the native code to write the file.
This is my code on React (NOT React native) project.
Here I read the file:
async readFileContent(path: string, isNotBin = true): Promise<string> {
if (this._isDownloadingFile) {
return Promise.reject();
}
let attempts = 0;
let pos = 0;
let fileContent = '';
let fileDownloadCompleted = false;
this.stopped = false;
let contentRead = '';
const chunkRead = [];
while (!fileDownloadCompleted && !this.stopped && attempts < 3) {
try {
const command = this.createReadFileCommand(path, pos);
const response: CommandResponse<FileReadResponse> = await utilityService.timeoutPromise(
this.bridgeService.sendCommand<
FileReadCommand,
FileReadResponse
>(command),
5000
);
if (response.retval == CommandResponseCode.OK) {
let newContent = response.data.data;
contentRead += newContent;
chunkRead.push(response.data);
const bytesCount = parseInt(response.data.count, 10);
const charsCount = bytesCount * 2;
if (response.data.count === "0") {
fileDownloadCompleted = true;
} else if (charsCount < newContent.length) {
newContent = newContent.substr(0, charsCount);
}
pos += bytesCount;
fileContent += this.hex2bin(newContent);
attempts = 0;
} else {
attempts++;
}
} catch {
attempts++;
}
}
this._isDownloadingFile = false;
if (fileDownloadCompleted) {
return Promise.resolve(fileContent);
} else {
return Promise.reject();
}
}
Here I do the translation:
private hex2bin(hex: string): string | string[] | Uint8Array {
const view = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
view[i / 2] = parseInt(hex.substring(i, i + 2), 16);
}
const bin = String.fromCharCode.apply(String, view);
return bin;
}
Here I send it to the native code:
viewFile(content: string, fileName: string): Promise<ViewFileResult> {
return new Promise<ViewFileResult>((resolve, reject) => {
this.sendNativeCommand('viewFile', [content, fileName]);
this.viewFileResultChange.subscribe(response =>
response !== undefined && response !== null
? resolve(response)
: reject()
);
});
}
Until there it seems all ok.
If I do a console.log(content) in viewFile function, the conten is correct.
But if I print what I receive in native viewFile function, there are a lot of characters added without any reason (that in hex code are equivalent to C2) and some part (not the final one) is cut off.
Does someone have any idea?
If I do a console.log(content) in viewFile function, the conten is correct.
I don't think so. A string in JavaScript is a sequence of UTF-16 chars, that is, a sequence of 2/4/8byte sequences, each one containing a char.
If you need to write a binary file, you should write binary content.
The hex2bin function should convert the hexadecimal string in input to a byte array; that is, it should just return view
. The return type of hex2bin
should accordingly be changed in Uint8Array
.
You will need to change sendNativeContent
(which is not shown, AFAICT) to use a binary signature, accepting a content that can be a Uint8Array
.
Any conversion of a binary sequence into a JavaScript string is going to permanently mangle the result.