With the following code,
var iconv = require('iconv-lite');
var msg = iconv.encode ('你好', 'gb18030');
console.log (msg);
I got
<Buffer c4 e3 ba c3>
Now, I need to get these bytes in binary. If I do a hexdump it should show as c4 e3 ba c3
So I tried msg.toString (), msg.toString ('binary'), none of them works correctly.
Any suggestions?
Related
I am trying to extract and format a mac address from a buffer as 00:04:a3:01:02:90
> const buffer = Buffer.from([0x00,0x04,0xa3,0x01,0x02,0x90]);
> console.log(buffer)
<Buffer 00 04 a3 01 02 90>
> console.log (buffer.slice(0, 6).map(byte => byte.toString(16).padStart(2, '0')).join(':'));
0:4:0:1:2:90
The output I am getting is removing the leading 0s and incorrectly displaying the third hex element 0xa3.
How do I correctly extract and format the bytes the mac address -> 00:04:a3:01:02:90?
Converting buffer into HEX string and then some string manipulation can give you the expected MAC Address. Try this script:
const buffer = Buffer.from([0x00,0x04,0xa3,0x01,0x02,0x90]);
const bufferString = buffer.toString('hex')
const macAddress = bufferString.split(/(..)/).filter(s => s).join(":")
console.log(macAddress)
I have the following code snippet in perl for automating an application script using Win32::OLE
use Win32::OLE;
use Win32::OLE::Variant;
my $app = new Win32::OLE 'Some.Application';
my $InfoPacket = "78 00 C4 10 95 B4
00 02 31 7F 80 FF";
my #Bytes = split(/[ \n][ \n]*/, $InfoPacket);
my #HexBytes;
foreach(#Bytes)
{
push #HexBytes, eval "0x$_";
}
my $Packet = pack("C12", #HexBytes);
my $VarPacket = Variant(VT_UI1, $Packet);
my $InfoObj = app -> ProcessPacket($VarPacket);
print $InfoObj -> Text();
I have converted the entire code in Python 3, except for the [exact] equivalent of pack() and Variant() functions.
from win32com.client import Dispatch
from struct import pack
app = Dispatch("Some.Application")
InfoPacket = "78 00 C4 10 95 B4 \
00 02 31 7F 80 FF"
Bytes = InfoPacket.split()
HexBytes = [int(b, 16) for b in Bytes]
Packet = pack('B'*12, *HexBytes) # This however, is not giving the exact same output as perl's...
VarPacket = ... # Need to know the python equivalent of above Variant() function...
InfoObj = app.ProcessPacket(VarPacket)
print (InfoObj.Text())
Please suggest the python equivalent of the pack() and Variant() functions used in perl script in the given context so that the final variable VarPacket can be used by Python's Dispatch object to properly generate the InfoObj object.
Thanks !!!
I am not sure about the Python equivalent of the Perl Variant, but for the first question about packing the unsigned char array, the following works for me:
from struct import pack
def gen_list():
info_packet = "78 00 C4 10 95 B4 00 02 31 7F 80 FF"
count = 0
for hex_str in info_packet.split():
yield int(hex_str, 16)
count += 1
for j in range(count, 120):
yield int(0)
packet = pack("120B", *list(gen_list()))
Edit
From the test file testPyComTest.py it looks like you can generate the variant like this:
import win32com.client
import pythoncom
variant = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_UI1, packet)
I have the following message:
message Message {
int64 id = 1;
google.protobuf.FloatValue weight = 2;
google.protobuf.FloatValue override_weight = 3;
}
and I wish to change the type of weight and override_weight(optional fields) to google.protobuf.DoubleValue so what I did was the fllowing:
message Message {
int64 id = 1;
oneof weight_oneof {
google.protobuf.FloatValue weight = 2 [deprecated=true];
google.protobuf.DoubleValue double_weight = 4;
}
oneof override_weight_oneof {
google.protobuf.FloatValue override_weight = 3 [deprecated=true];
google.protobuf.DoubleValue double_override_weight = 5;
}
}
My question is, lets assume I have old messages who were compiled by the previous protobuff message compiler for the old message, would I be able to parse them as the new message?
The documentation is very vague about this:
"Move optional fields into or out of a oneof: You may lose some of your information (some fields will be cleared) after the message is serialized and parsed. However, you can safely move a single field into a new oneof and may be able to move multiple fields if it is known that only one is ever set."
Has anyone tried this before? what is the best practice for this situation?
As far as I know fields in an oneof are just serialize using their tag number. The serialized data does not indicate if a field is part of an oneof. This is all handled by the serializer and deserializer. So as long as the tag numbers do not conflict it can be assumed that it will work in both directions, old messages to a new serializer and new messages to an old serializer.
You could test this using an online protobuf deserializer.
Verification:
The code does indeed produce the same byte strings. Below you will find the message definitions and python code I used. The python code will output a byte string you can copy and use in the decoder of Marc Gravell.
syntax = "proto3";
message MessageA {
int64 id = 1;
float weight = 2;
float override_weight = 3;
}
message MessageB {
int64 id = 1;
oneof weight_oneof {
float weight = 2 [deprecated=true];
double double_weight = 4;
}
oneof override_weight_oneof {
float override_weight = 3 [deprecated=true];
double double_override_weight = 5;
}
}
import Example_pb2
# Set some data in the original message
msgA = Example_pb2.MessageA()
msgA.id = 1234
msgA.weight = 3.21
msgA.override_weight = 5.43
# Output the serialized bytes in a pretty format
str = 'msgA = '
for x in msgA.SerializeToString():
str += "{:02x} ".format(x)
print(str)
# Next set the original fields in the new message
msgB = Example_pb2.MessageB()
msgB.id = 1234
msgB.weight = 3.21
msgB.override_weight = 5.43
# Output the serialized bytes in a pretty format
str = 'msgB 1 = '
for x in msgB.SerializeToString():
str += "{:02x} ".format(x)
print(str)
# And finally set the new fields in msgB
msgB.double_weight = 3.21
msgB.double_override_weight = 5.43
# Output the serialized bytes in a pretty format
str = 'msgB 2 = '
for x in msgB.SerializeToString():
str += "{:02x} ".format(x)
print(str)
The output of the python script was:
msgA = 08 d2 09 15 a4 70 4d 40 1d 8f c2 ad 40
msgB 1 = 08 d2 09 15 a4 70 4d 40 1d 8f c2 ad 40
msgB 2 = 08 d2 09 21 ae 47 e1 7a 14 ae 09 40 29 b8 1e 85 eb 51 b8 15 40
As you can see message A and message B yield the same byte string when setting the original fields. Only when you set the new fields you get a different string.
I'm trying to convert a text string AAIA to binary. This is how Salesforce manages dependent picklists.
I essentially need to go from ascii to base64 to binary, but I think the binary needs to be bytes, not text.
Expected result is AAIA => 00000000 00000010 00000000, which means 15th item in my other list controls this one. I can't figure out how to make this work in Node! Using the above mentioned values on this site works, but no luck in Node.
You want to convert a string to binary.
You want to convert a string value of AAIA to 00000000 00000010 00000000.
You want to achieve this using Node.js.
If my understanding is correct, how about this answer?
Sample script:
In this sample, there are the outputs of 3 patterns.
const str = "AAIA";
// Pattern 1
const buf = Buffer.from(str, 'base64');
console.log(buf); // <--- <Buffer 00 02 00>
// Pattern 2
const byteAr = Uint8Array.from(buf);
console.log(byteAr); // <--- Uint8Array [ 0, 2, 0 ]
// Pattern 3
const result = buf.reduce((s, e) => {
const temp = e.toString(2);
return s += "00000000".substring(temp.length) + temp + " ";
}, "");
console.log(result); // <--- 00000000 00000010 00000000
References:
Buffer.from(string[, encoding])
Uint8Array
toString()
If I misunderstood your question and these were not the results you want, I apologize.
I want log the buffer to string, but I am not want to use buffer.toString() method
console.log(new Buffer(12))
show
< Buffer 00 22 33 11 55 ...>
but console.log('buffer:' + new Buffer(12))
show
buffer: something can't read
I want
buffer: < Buffer 00 22 33 11 55 ...>
Doing
var b = new Buffer([0x41, 0x42, 0x43, 0x44]);
console.log(b);
// <Buffer 41 42 43 44>
is the same as doing
console.log(b.inspect());
whereas
var b = new Buffer([0x41, 0x42, 0x43, 0x44]);
console.log('str' + b);
// strABCD
is the same as doing
console.log('str' + b.toString());
because using string concatenation using + automatically converts both sides of the operator to strings using .toString(). console.log(...) on the other hand converts its arguments to strings by calling .inspect() when possible.
The easiest way to do what you want to do is to just let console.log do its thing by passing it multiple arguments
console.log('buffer:', new Buffer(12))
Note, the , instead of a +, so instead of concatenating using .toString, you let console.log stringify each of its arguments on its own.