why common-io tool IOUtils.toByteArray is not same? - character-encoding

Why aren't the results the same when using commons.io.IOUtils to get byte[]?
The toByteArray method params are Inputstream and Reader.
String file = "c:/c.pdf";
try (InputStream is = new FileInputStream(file)) {
byte[] result = IOUtils.toByteArray(is);
System.err.println(Arrays.toString(result));
} catch (Exception e) {
e.printStackTrace();
}
try (Reader reader = new FileReader(file)) {
byte[] result = IOUtils.toByteArray(reader,"gbk");
System.err.println(Arrays.toString(result));
} catch (Exception e) {
e.printStackTrace();
}

Short answer: the two results are different because the 2nd solution is wrong. Never use a Reader to read binary data.
An InputStream reads the bytes of a file without trying to give them any meaning; a Reader, on the contrary, tries to convert them to characters using a specific charset: your 2nd example reads bytes, converts them to characters and then the toByteArray() method converts these characters back to bytes BUT this double conversion is not only unuseful (obvious), it's quite wrong because the first conversion may fail: when the Reader encounters a byte (or a group of bytes in case of multi-byte charsets like GBK) that has no associated character it returns a question mark character and when you convert these question marks back to bytes you get the byte value corresponding to the question mark not the original value that failed the conversion.
So the problem is not in IOUtils, it is in your usage of a Reader for reading a PDF.

Related

How to parse an Incoming stream of caller id through a modem, if data come as chunked?

I am developing a dart application where I want to read the Caller Id from an incoming phone call. Hence I did the following minimalistic example:
import 'package:libserialport/flutter_libserialport.dart';
void main(){
final SerialPort port = SerialPort("/dev/ttyACM0");
if(!port.openReadWrite()){
print(SerialPort.lastError);
exit(-1);
}
port.write("ATZ\r\n");
port.write("AT+VCID=1\r\n");
final reader = SerialPortReader(port);
reader.stream.listen((data) {
String response = String.fromCharCodes(data);
RegExp regExp = new RegExp("NMBR[\s=]*(?<phoneNumber>\+*[0-9\s]+)");
Iterable<RegExpMatch> matches = regExp.allMatches(response);
for (final m in matches) {
print "Matched Number $m";
}
});
}
The issue is that I want to retrieve a full phone number from a continuous input stream of data.
A case that I may have that I receive the following from the serial device:
blahblayblahblah\r\n
34321123\r\n
4456634\r\n
blahblayblahblahblahblayblahblahblahblayblahblahblahblayblahblahblahblayblahblahblahblayblahblah\r\n
NMBR=0030003045655566\r\n
\r\n
OK\r\n
\r\n
And the incoming data bay be called like this:
data "blahblayblahblah\r\n"
data "4456634\r\n"
data "blahblayblahblahblahblay"
....
data "NMBR=00304565"
data "5566\r\n"
As you can see I expect that from the string NMBR=0030003045655566 that I want to extract the number 0030003045655566 may not come as a whole but in chinked parts.
How I can manage this?
An approach that I though is to keep a buffer of data
String dataWhereIcanExtractPhoneNumbers = ""
reader.stream.listen((data) {
String response = String.fromCharCodes(data);
dataWhereIcanExtractPhoneNumbers += response;
RegExp regExp = new RegExp("NMBR[\s=]*(?<phoneNumber>\+*[0-9\s]+)");
Iterable<RegExpMatch> matches = regExp.allMatches(dataWhereIcanExtractPhoneNumbers);
for (final m in matches) {
print "Matched Number $m";
}
});
But how I can clean it up from all unnecessary junk (responses that do not contain caller Id)?

Java 8 issues printing PS to network printer

Got a weird question for you. Recently upleveled my old project from java 7(jdk1.7.0_10) to java 8(1.8.0.91.x86_64). In java 7 it printed the post script file with no issues and now it is printing the postscript file as plain text instead of converting the file. This is on a redhat linux environment. Simply I am trying to print a string containing a post script file of a file itself.
Here is my original code
DocFlavor flavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
PrintService pService = PrintServiceLookup.lookupDefaultPrintService();
// In a field environment, send to the printer
if (System.getenv("USER_DEFINED_RELTOP") == null || pfr.exists()) {
if (pService.getName().isEmpty()) {
LOGGER.error("No printer selected");
} else {
LOGGER.info("Printing to " + pService.getName());
DocPrintJob pj = pService.createPrintJob();
try {
InputStream is = new ByteArrayInputStream(data.getBytes("UTF8"));
Doc doc = new SimpleDoc(is, flavor, null);
PrintJobWatcher pjw = new PrintJobWatcher(pj);
pj.print(doc, null);
pjw.waitForDone();
is.close();
} catch (PrintException | IOException e) {
LOGGER.error(e);
} // try block
} // no printer selected
// Otherwise, send to a file
} else {
That worked fine in java 7, I updated it to the oracle spec found here for java 8.
https://docs.oracle.com/javase/8/docs/api/javax/print/PrintService.html#createPrintJob--
https://docs.oracle.com/javase/8/docs/technotes/guides/jps/spec/printing.fm6.html
DocFlavor psFlavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet();
attrs.add(MediaSizeName.ISO_A4);
PrintService[] pservices = PrintServiceLookup.lookupPrintServices(psFlavor,
attrs);
File pfr = new File(PFR_INDICATOR);
// In a field environment, send to the printer
if (System.getenv("USER_DEFINED_RELTOP") == null || pfr.exists()) {
//Check we have a printer capable of post script
if (pservices.length > 0) {
LOGGER.info("Printing to " + pservices[0].getName());
DocPrintJob pj = pservices[0].createPrintJob();
try {
InputStream fis = new ByteArrayInputStream(data.getBytes("UTF8"));
//byte[] ba =data.getBytes("UTF8");
Doc doc = new SimpleDoc(fis, psFlavor, null);
LOGGER.info("Doc Flavor " + doc.getDocFlavor());
PrintJobWatcher pjw = new PrintJobWatcher(pj);
LOGGER.info("PrintJob Attributes : " + pj.getAttributes());
pj.print(doc, attrs);
pjw.waitForDone();
fis.close();
} catch (IOException e) {
LOGGER.error(e);
NotificationDialog.show(NotificationDialog.NOTICE_TYPE.ERROR, PRINT_ERROR);
} catch (PrintException e) {
LOGGER.error(e);
}
} else { // no printer selected
This gives me an error java.awt.print.PrinterIOException: java.io.IOException: /usr/bin/lpr: where it looks to not find lpr.
If I keep it the way it was originally (not write to file) it prints the postscript as plain text even if adding the check to check if the printer is post script capable. If I use the new way of printing file I get a lpr not found error. If I print the PS document using the command lpr it converts it as expected and prints fine. If I use lpr -l that doesn't format it prints it document as plain text as well.
Any suggestion/help would be great. I am lost on what to do. I really don't want to convert it to an image and print that.
At a guess I'd say that your printer is an HP or at least PCL + PS printer, not a pure PostScript-only printer.
In that case you generally need to prepend the PostScript with a language selection PJL string. If you don't do this then it usually defaults to PCL and if you don't send any PCL commands (which all begin with 0x1B) then everything is treated as plain ASCII text. That would explain why both your application and lpr -l end up writing text, but lpr itself doesn't (presumably it adds the PJL).
You could try prepending the PostScript file with something like:
%-12345X#PJL JOB
#PJL ENTER LANGUAGE=POSTSCRIPT
NB the first byte there, before the % should be a 0x1b ESC character, but I can't readily paste binary....
Try sending the file with lpr -l if that works then you could try your old printing method.

How do I use Bouncy Castle to read an App Store In App Purchase receipt? (PKCS7)

I have a receipt in PKCS7 that I obtained from my iOS app. Apple says this is a PKCS7 structure, and within that, is information regarding past recurring purchases.
I have the raw receipt here, encoded in Base64.
I've sent this payload, with my secret key, to Apple and got this response. Based on WWDC videos, and documentation, I believe I should be able to read this receipt directly, and without sending it to apple.
I'm guessing that PEMReader in BC is the correct starting point parse it, however I'm not sure how to actually use it. I've scanned the BC source code for the strings "PKCS", and looked at unit tests, however all I ever see are casts from PEMReader into another format.
using (var stream1 = new MemoryStream(receipt.Data))
using (var stream2 = new StreamReader(stream1))
{
var pp = new PemReader(stream2);
pp.ReadObject();
}
Question
How do I use Bouncy Castle to verify a raw receipt payload generated from Apple Store?
Note to self: I intend to use this to inspect the actual binary to see if ApplicationUsername is included in the receipt, yet for some reason isn't returned in the JSON result when posting the server. (Bug on Apple's side?)
I've made this using Java 7 and BouncyCastle 1.56.
For the code below, consider that pemString is the PEM string you provided. But I had to make some modifications:
format (break lines for every 64 characters) - I've made a small program to do that
include BEGIN and END headers
So my PEM looks like:
-----BEGIN PKCS7-----
MIIv5gYJKoZIhvcNAQcCoIIv1zCCL9MCAQExCzAJBgUrDgMCGgUAMIIfhwYJKoZI
hvcNAQcBoIIfeASCH3Qxgh9wMAoCAQgCAQEEAhYAMAoCARQCAQEEAgwAMAsCAQEC
AQEEAwIBADALAgELAgEBBAMCAQAwCwIBDwIBAQQDAgEAMAsCARACAQEEAwIBADAL
....
gdTu2uzkTyT+vcBlaLHK1ZpjKozsBds7ys6Q4EFp7OLxtJTj7saEDYXCNQtXBjwl
UfSGvQkXeIbsaqSPvOVIE83K3ki5i64gccA=
-----END PKCS7-----
For the code below, I followed the definition in Apple's doc:
ReceiptAttribute ::= SEQUENCE {
type INTEGER,
version INTEGER,
value OCTET STRING
}
Payload ::= SET OF ReceiptAttribute
Code:
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DLSequence;
import org.bouncycastle.asn1.DLSet;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
String pemString = // PEM String as described above
PemReader reader = new PemReader(new StringReader(pemString));
PemObject pemObject = reader.readPemObject();
reader.close();
CMSSignedData s = new CMSSignedData(pemObject.getContent());
byte[] content = (byte[]) s.getSignedContent().getContent();
ASN1InputStream in = new ASN1InputStream(content);
// Payload: a SET of ReceiptAttribute
DLSet set = (DLSet) DLSet.fromByteArray(in.readObject().getEncoded());
int size = set.size();
for (int i = 0; i < size; i++) {
// ReceiptAttribute is a SEQUENCE
DLSequence seq = (DLSequence) set.getObjectAt(i);
// value is the third element of the sequence
DEROctetString oct = (DEROctetString) seq.getObjectAt(2);
ASN1Object obj = readObject(oct.getOctets()); // *** see comments below ***
}
in.close();
// readObject method
public ASN1Object readObject(byte[] b) throws IOException {
ASN1InputStream in = null;
try {
in = new ASN1InputStream(b);
return in.readObject();
} catch (Exception e) {
// if error occurs, just return the octet string
return new DEROctetString(b);
} finally {
in.close();
}
}
Variable obj will be the content of the ReceiptAttribute, and it can vary a lot - I've seen DERIA5String, DERUTF8String, ASN1Integer and many others. As I don't know all possible values of this field, I think it's up to you to check each value.

Saving photo to the remote server from the blackberry application

Can any one please tell me the process through which I can open a photo gallery in the blackberry application to choose a photo to upload, is there any file uploading control in the blackeberry 5.0 and also tell me the process to save the photo from the blackberry application to the remote server using HttpWebRequest.
Thanks
Their is nice way which i have done. Just get selected image from the phone through file browser or file io method than convert it to a byte array than just encode it to base64 String and send this string to the server by http request.
and at server side just do opposite.
final byte[] chunk;
chunk = new byte[actualSize];
try {
int bytesRead = in.read(chunk);
fconn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try
{
String encodedStr = Base64OutputStream.encodeAsString(chunk, 0, chunk.length,false,false);
}

writing to text file in blackberry

is there any way out that we can make the data in text file persistent? everytime a user finishes playing a game, in my program his name and respective score is written to a text file. When the next player comes the previous one gets overwritten. since am writing in write mode, I am not sure whether append mode is supported to save scores of this sort in blackberry...any suggestions are welcome
You should really use the PersistentStore to store this type of information - it's much easier to use and probably more reliable than trying to write files.
However, if you insist on writing files, here's the general code to open a file for appending:
private OutputStream openFileForWriting(String filePath) {
try {
FileConnection fconn = (FileConnection) Connector.open(filePath);
// If no exception is thrown, then the URI is valid, but the file may or may not exist.
if (!fconn.exists()) {
fconn.create(); // create the file if it doesn't exist
}
return fconn.openOutputStream(fconn.fileSize());
} catch (IOException ioe) {
System.out.println("Could not open " + filePath + " for writing");
}
return null;
}

Resources