0

I am using a ThermalPrinter for recipes in java, or i try to. This printer accepts only Text for printing, so i need to send all commands as strings. Most are just some sequence of the asci commands. So i collect all the text i want to print and all commands that need to be done in one String and then send this to the printer. I add the commands to my string like this:

final byte[] bytes = {0x1B, 0x25, 0x18};
printString += new String(bytes);

This works fine except for on case. In the final Command to cut the paper on of the values is 0xF0. this works out to -16 since java interprets byte as signed value. If then add this to the string it adds not the bytes i want. It adds 3 bytes instead which will be for the -16 as text. But it should just add the one byte.

If i run this:

        final byte[] bytes = {0x1B, (byte) 0xF0 , 0x06, 0x01, 0x01};
        String newString = new String(bytes);

        for (byte b : bytes) {
            System.out.print(b + " ");
        }
        System.out.println();

        for (byte b : newString.getBytes()) {
            System.out.print(b + " ");
        }
        System.out.println();

It gives me:

27 -16 6 1 1 
27 -17 -65 -67 6 1 1 

The byte array contains the correct value but not the string. I would expect the two outputs to be the same. Is this a limitation of the String class? Or is there a way to do this?

Some more information. The printer is a Hengstler eXtendo X-56. To communicate to the printer i use the API supplied by the Manufacturer. Its a C lib i add to my system(debian) and then load via JNA. The Method from api header i use to print data.

int exo_api_printer_write(intptr_t printer, unsigned char * data, int size, unsigned long timeout_ms)

The JNA interface funtion looks like:

int exo_api_printer_write(Pointer printer, String data, int size, long timeout_ms);

So at some point i Have to convert my bytes into a String to send it to the printer. My Problem now is the printer command to cute the paper. The command is: 0x1B, 0xF0, 0x06, 0x01, 0x01 and cannot convert this to a string.

Grebnelloh
  • 11
  • 3
  • 2
    Strings are not collections of bytes in Java. – aled Jun 01 '23 at 22:11
  • 1
    Can you share how do you communicate to the printer? An output stream? – aled Jun 01 '23 at 22:18
  • 2
    use the `ISO8859_1` Charset - then you should get same results... better would be to use the Charset is used/expected by the printer or send the bytes directly - I lot of assumption on my side... this question looks like an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/66378#66378), maybe better explain what you are trying to accomplish – user16320675 Jun 01 '23 at 22:29
  • So, a negative number can't be represented as an ASCII character. Is there any other way to send the _0xf0_ command? – Reilas Jun 02 '23 at 00:47
  • 2
    Welcome to Stack Overflow. "This printer accepts only Text for printing," - **which printer is it**? Exactly **what does the documentation say**, about how to communicate with it? What **code do you write, using the resulting string**, in order to make the printing happen? Please read [mre] and make sure that someone else could **copy and paste** the code, **without adding or changing anything**, to see the **exact problem, directly**. – Karl Knechtel Jun 02 '23 at 02:08
  • You could also try using Base64 if you want a proper conversion between bytes and strings (but these strings are just a different representation of bytes) – dan1st Jun 02 '23 at 06:31
  • I added some more information. I hope this makes a little more clear what the problem is or i try to achieve. – Grebnelloh Jun 02 '23 at 12:38
  • Does this answer your question? [How to convert a byte array to a hex string in Java?](https://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to-a-hex-string-in-java) – Jorn Jun 02 '23 at 12:58

4 Answers4

1

I figured out a solution. It is actually a combination from the answers here.

The solution for me, however, was to alter the JNA interface. Since the print method expects a char* i just thought great i will use a string. But i had to use a byte[] on the java side here. Now i can send all the data as i want to. This way i don`t need to use a string in any way. I guess my problem then, was that i used a string for something it is not intended for.

In case someone need it at some time, here the full JNA interface as i use it now(You need to intstall the Hengstler API to your system):

public interface ExoAPI extends Library {
ExoAPI INSTANCE = (ExoAPI) Native.load("ExoApi", ExoAPI.class);

String exo_api_get_library_info();
long exo_api_printer_open(String port);
int exo_api_printer_set_serial(long printer, long baud_rate, char data_bits, char parity, char stop_bits);
void exo_api_printer_close(long printer);
int exo_api_printer_write(long printer, byte[] data, int size, long timeout_ms);
int exo_api_printer_read(long printer, byte[] data, int size, long timeout_ms);
int exo_api_printer_clear(long printer);
}
Grebnelloh
  • 11
  • 3
0

If you use ISO/IEC 8859-1 for encoding, it appears to preserve the -16 byte.

byte[] bytes = { 0x1b, (byte) 0xf0, 0x06, 0x01, 0x01 };

String stringA = new String(bytes, StandardCharsets.ISO_8859_1);
String stringB = new String(bytes, StandardCharsets.UTF_8);
String stringC = new String(bytes, StandardCharsets.US_ASCII);

System.out.println(Arrays.toString(stringA.getBytes(StandardCharsets.ISO_8859_1)));
System.out.println(Arrays.toString(stringB.getBytes(StandardCharsets.UTF_8)));
System.out.println(Arrays.toString(stringC.getBytes(StandardCharsets.US_ASCII)));

Output

[27, -16, 6, 1, 1]
[27, -17, -65, -67, 6, 1, 1]
[27, 63, 6, 1, 1]
Reilas
  • 3,297
  • 2
  • 4
  • 17
  • I think the OP needs to send the data from one communicator to another using `String`s _This printer accepts only Text for printing, so i need to send all commands as strings_ – dan1st Jun 02 '23 at 06:30
  • @dan1st, thanks, I updated the answer. It looks like they just need to use an encoding when creating the _String_. – Reilas Jun 02 '23 at 13:40
0

When converting between strings and byte arrays, you are using some encoding mechanism. If you don't specify it, it will use the default encoding for your platform. In your case, it seems to be UTF-8 because some characters are encoded on 3 bytes. With the ISO-8859-1 encoding, each character is encoded as a single byte. Try using it instead:

...
import static java.nio.charset.StandardCharsets.ISO_8859_1;
...

    final byte[] bytes = {0x1B, (byte) 0xF0 , 0x06, 0x01, 0x01};
    String newString = new String(bytes, ISO_8859_1);

    for (byte b : bytes) {
        System.out.print(b + " ");
    }
    System.out.println();

    for (byte b : newString.getBytes(ISO_8859_1)) {
        System.out.print(b + " ");
    }
    System.out.println();
Maurice Perry
  • 32,610
  • 9
  • 70
  • 97
0

Since the API you are working with expects a char[] and you seem to want to send raw data there, just create a Java char[], create a String from that and then call it with that:

final char[] chars={0x1B, 0xF0, 0x06, 0x01, 0x01};
String newString = String.valueOf(chars);
//send newString to the printer

//some tests
for(char c:chars){
    System.out.print((int)c);
    System.out.print(' ');
}
byte[] bytes = newString.getBytes();
for(byte b:bytes){
    System.out.print(b);
    System.out.print(' ');
}
dan1st
  • 12,568
  • 8
  • 34
  • 67