I am struggling to convert a base64 string to a list of UnsignedInteger16 values. I have limited experience with mathematica, so please excuse me if this should be obvious.
I read the base64 string from an XML file and ultimately into a variable base64String. This is a long string with 7057 UnsignedInteger16 values, but it starts off as: "8ynnKdspzinCKbcprSmhKZUpiCl8KW8pYylXKUkpQCk0KSop..."
Can convert to ByteArry with n = BaseDecode[base64String] // Normal;
Then n has the expected values {243, 41, 231, 41, 219, 41, 206, 41, 194, 41, 183, 41, 173, 41, 161, ...
However, what I am looking for is a list with the values {243 + 256 * 41, 231 + 256 * 41, 219 + 256 * 41, ...
i.e.: {10739, 10727, 10727, ...
Thank you in advance for you suggestions.
Edit: Thank you for the suggestion to use Partition. Works well. For the interests in improving my understanding, can any one suggest why I cannot get ImportString[...] to work.
My source data is XML file with data along the lines of the following where I truncated the Base64 string for clarity.:
<?xml version="1.0" encoding="utf-8" ?>
<BPplus version="5.0" filename="BPplus_00100.xml">
<MeasDataLogger guid="ee7bee36-ffd6-30ae-53f1-257f0eab7ddd">
<Sys>130</Sys>
<Dia>77</Dia>
<Map>101</Map>
<PressureWaves>
<RawPressureWave>
<RawPressure>NIBP</RawPressure>
<RawSampleCount>7057</RawSampleCount>
<RawCuffPressureWave>8ynnKdspzinCKbcprSmhKZUpiCl8KW8pYylXKUk... bU1mjV+NWM1RjU=</RawCuffPressureWave>
</RawPressureWave>
</PressureWaves>
</MeasDataLogger>
</BPplus>
The script I then run with the C1, C2 & C3 suggestions.
sampleFilenameString = "C:\\BPPdata\\BPplus_00112.xml";
xmldata = Import[sampleFilenameString, "XML"];
RawCuffPressureWave =
Cases[xmldata, XMLElement["RawCuffPressureWave", _, _], Infinity];
nibpxml = RawCuffPressureWave[[2]];
base64String = ToString[nibpxml[[3]]];
C1 = Partition[Normal@BaseDecode[base64String], 2].{1, 256};
C2 = ImportByteArray[BaseDecode[base64String], "UnsignedInteger16"];
C3 = ImportString[base64String, {"Base64", "UnsignedInteger16"},
ByteOrdering -> -1]
C1 == C2
C1 == C3
C1
produces the following output
{17956, 26977, 25964}
True
False
{10739, 10727, 10715, 10702, 10690, 10679, 10669, 10657, ... }
I have tried to make the first parameter ToString[base64String]
, but that did not change the outcome.
If I manually define the string $base64 = "8ynnKdspzinCKbcprSmhKZUpiCl8KW8pYylXKUkpQCk0KSo....
It works as expected and C1 = C4
C4 = ImportString[$base64, {"Base64", "UnsignedInteger16"},
ByteOrdering -> -1];
C1 == C4
Can anyone explain the difference why $base64
variable works but base64String
does not?
Edit: base64String is not a string! Not sure if this is the best way to convert, but it works in Mathematica 11.x and higher.
sampleFilenameString = "C:\\BPPdata\\BPplus_00112.xml";
xmldata = Import[sampleFilenameString, "XML"];
RawCuffPressureWave = Cases[xmldata, XMLElement["RawCuffPressureWave", _, _], Infinity];
nibpxml = RawCuffPressureWave[[2]];
(* convert to string then base64 decode *)
base64Data =
Developer`DecodeBase64ToByteArray[
nibpxml //. XMLElement[_, _, t_] :> t // Flatten // StringJoin] // Normal;
C1 = Partition[base64Data, 2].{1, 256};
ImportByteArray[BaseDecode[str], "UnsignedInteger16"]
? $\endgroup$Partition[n, 2].{1, 256}
$\endgroup$(* convert to string then base64 decode *) base64Data = Developer`DecodeBase64ToByteArray[ ToString[ nibpxml //. XMLElement[_, _, t_] :> t // Flatten // StringJoin]] // Normal; C1 = Partition[base64Data, 2].{1, 256};
$\endgroup$base64String
in the question contains extraneous braces, i.e."{8ynnKdsp...}"
. This is not a valid Base64 string -- but apparentlyBaseDecode
will ignore such errors and process it anyway. Note how the content portion of the XML element is actually a list:XMLElement["RawCuffPressureWave", {}, {"8ynnKdsp..."}]
. The call toToString
converts the entire list to a string, braces and all. Assuming the content of the XML element RawCuffPressureWave is always a single text node then the simplest fix isbase64String = nibpxml[[3, 1]]
. $\endgroup$nibpxml[[3]]
being a list and the need to index to the first item to get the value withnibpxml[[3,1]]
. Probably a bit obvious in retrospect, but eluded me a few days ago. I will remember! :-) $\endgroup$