(Java + Android) Parsing string to float strange error - java

This may sound like a trivial question, but I'm having a really hard time trying to figure it out. Basically I'm sending a string from my Android to my PC. All the connection is ok, and the string is transfered successfully. This is the Android code (sends string to computer):
try
{
println(scSocket + "");
if (scSocket!=null)
{
SendReceiveBytes sendReceiveBT = new SendReceiveBytes(scSocket);
String red = rotZ + " \n";
byte[] myByte = stringToBytesUTFCustom(red);
sendReceiveBT.write(myByte);
}
}
catch(Exception e)
{
println(e);
}
Where rotZ is what I want to send, it is a "float" value. I need to put the " \n" on the end of the message so that it will be recognized as a full message on the PC. So far so good. Now I want to read this on my PC, which is achieved by:
//BlueTooth
String lineRead = "";
try
{
lineRead = new String(sampleSPPServer.readFromDevice());
if(lineRead != null && !lineRead.isEmpty())
{
String lineTransf = lineRead.replace("\n", "").replace("\r", "").replace(" ", "").replace("\"", "").trim();
println("LineTransf: " + lineTransf);
rotZ += 0.01*(Float.parseFloat(lineTransf));
println("Zrotation: " + rotZ); //Never gets here, throws and error before...
}
else
rotZ += 0;
}
catch(Exception e)
{
println("Exception: " + e);
}
Which gives me the error:
NumberFormatException: invalid float value: "1.1400002"
In my code you can see I check for null, empty, etc. So that's not the problem. I've already tried:
NumberFormat nf = NumberFormat.getInstance(Locale.US);
rotZ += 0.01*(nf.parse(lineTransf).floatValue());
Got the same result... In stackoverflow there is a similar question:
Here
There is one more strange thing, If I try the code:
for(int i = 0; i < lineTransf.length(); i++)
println(lineTransf.substring(i,1));
I get that the string's length is 19, but it only prints the first two and gives the message:
Exception: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
Even more strange thing, when I did ctrl-c, ctrl-v on the number "1.1400002" that appears in the console, it only pastes "1" here on stack overflow.
I know that the number is right, but somewhere the conversion is not. I think that's because the string is sent as a byte and read as a String, but how do I solve this problem? Thanks in advance!!

Nothing strange. that's the expected behavior of substring. It throws an IndexOutOfBoundsException, if the startIndex is negative, the endIndex is greater than the string's length or if startIndex is greater the endIndex (which is your case). To me it looks like you want to print the char at index. Try with
for(int i = 0; i < lineTransf.length(); i++)
println(lineTransf.charAt(i));

I found a work around, but I really, really would like an explanation (if possible), because this is just too ugly... I changed the code to:
//BlueTooth
String lineRead = "";
try
{
lineRead = new String(sampleSPPServer.readFromDevice());
if(lineRead != null && !lineRead.isEmpty())
{
String lineTransf = lineRead.replace("\n", "").replace("\r", "").replace(" ", "").replace("\"", "").trim();
println("LineTransf: " + lineTransf + " " + lineTransf.length());
String lastTry = "";
for(int i = 0; i < lineTransf.length(); i++)
{
if(lineTransf.charAt(i) != ' ' && lineTransf.charAt(i) != '\u0000')
{
println(lineTransf.charAt(i));
lastTry += lineTransf.charAt(i);
}
}
println("LastTry: " + lastTry);
rotZ += 0.01*(Float.parseFloat(lastTry));
println("Zrotation: " + rotZ);
}
else
rotZ += 0;
//System.out.println("Line Read:" + lineRead);
}
catch(Exception e)
{
println("Exception: " + e);
}
I'm basically creating a new String called lastTry and then checking if each of the bluetooth read characters are not empty(?) null(?) (since I'm testing for:)
if(lineTransf.charAt(i) != ' ' && lineTransf.charAt(i) != '\u0000')
And if they pass this test I individually "assemble" the lastTry String. It seems that the bluetooth is sending a null character between each of the characters of the whole string. I don't understand why this happens and it actually consumes some time while reading the incoming string. I really would love another answer if someone have another idea...

Related

Verify the byte range of a PDSignature in a pdf file using PDFBox

I have loaded a PDDocument.
I retrieved the PDSignature object named sig.
The byte range of the signature is provided by sig.getByteRange(). In my case it is:
0-18373 43144-46015
I want to verify that the byte range of the signature is valid.
Because the signature has to verify the whole file expect itself.
Also the byte range is provided by the signature so I cannot rely on it.
I can check the first value to be 0 and the last value has to be the size of the file -1.
But I also need to verify the second and the third value (18373 and 43144). Therefore I need to know the position of the PDSignature in the document and its length.
How do I get these?
Have a look at the PDFBox example ShowSignature. It does this indirectly: It checks whether the bytes in the gap of the byte ranges coincide exactly with the signature value determined by document parsing.
In the method showSignature:
int[] byteRange = sig.getByteRange();
if (byteRange.length != 4)
{
System.err.println("Signature byteRange must have 4 items");
}
else
{
long fileLen = infile.length();
long rangeMax = byteRange[2] + (long) byteRange[3];
// multiply content length with 2 (because it is in hex in the PDF) and add 2 for < and >
int contentLen = contents.getString().length() * 2 + 2;
if (fileLen != rangeMax || byteRange[0] != 0 || byteRange[1] + contentLen != byteRange[2])
{
// a false result doesn't necessarily mean that the PDF is a fake
// see this answer why:
// https://stackoverflow.com/a/48185913/535646
System.out.println("Signature does not cover whole document");
}
else
{
System.out.println("Signature covers whole document");
}
checkContentValueWithFile(infile, byteRange, contents);
}
The helper method checkContentValueWithFile:
private void checkContentValueWithFile(File file, int[] byteRange, COSString contents) throws IOException
{
// https://stackoverflow.com/questions/55049270
// comment by mkl: check whether gap contains a hex value equal
// byte-by-byte to the Content value, to prevent attacker from using a literal string
// to allow extra space
try (RandomAccessBufferedFileInputStream raf = new RandomAccessBufferedFileInputStream(file))
{
raf.seek(byteRange[1]);
int c = raf.read();
if (c != '<')
{
System.err.println("'<' expected at offset " + byteRange[1] + ", but got " + (char) c);
}
byte[] contentFromFile = raf.readFully(byteRange[2] - byteRange[1] - 2);
byte[] contentAsHex = Hex.getString(contents.getBytes()).getBytes(Charsets.US_ASCII);
if (contentFromFile.length != contentAsHex.length)
{
System.err.println("Raw content length from file is " +
contentFromFile.length +
", but internal content string in hex has length " +
contentAsHex.length);
}
// Compare the two, we can't do byte comparison because of upper/lower case
// also check that it is really hex
for (int i = 0; i < contentFromFile.length; ++i)
{
try
{
if (Integer.parseInt(String.valueOf((char) contentFromFile[i]), 16) !=
Integer.parseInt(String.valueOf((char) contentAsHex[i]), 16))
{
System.err.println("Possible manipulation at file offset " +
(byteRange[1] + i + 1) + " in signature content");
break;
}
}
catch (NumberFormatException ex)
{
System.err.println("Incorrect hex value");
System.err.println("Possible manipulation at file offset " +
(byteRange[1] + i + 1) + " in signature content");
break;
}
}
c = raf.read();
if (c != '>')
{
System.err.println("'>' expected at offset " + byteRange[2] + ", but got " + (char) c);
}
}
}
(Strictly speaking a binary string in normal brackets would also be ok as long as it fills the whole gap, it needn't be a hex string.)

java.lang.OutOfMemoryError during String concatenation

I get java.lang.OutOfMemoryError during String concatenation. Can somebody help me get rid of this? Below is how my code looks. This whole if blokc is run under a loop and when it is processing string concatenation for "str", it throws OutofemoryError. Any help on this much appreciated.
for (long j = mincollectiontime; j <= maxcollectiontime; j = j
+ timeintreval) {
query = "select count(*) table1";
ResultSet result2 = VerticaDBHandler.executequery(con2, query);
System.out.println("Query:- " + query);
String str = "";
if (result2.isBeforeFirst()) {
if (mysqlconn == null) {
mysqlconn = DatabaseHandler.openDB();
}
while (result2.next()) {
int isgap = Integer.parseInt(result2.getString(1));
if (isgap == 0) {
Date startime = EpochTimeHandler.epochToTimeStamp(j);
Date endtime = EpochTimeHandler.epochToTimeStamp(j
+ timeintreval);
str = "NO DATA BETWEEN " + startime + " --- " + endtime
+ " forInstanceId: " + instanceid
+ " --InstanceName: " + instanceName + " in "
+ perfTables[i];
DatabaseHandler.LoadDB_dataGaps(mysqlconn,
perfTables[i], instanceid, instanceName,
VirtType, BelongstoDataCenter,
startime.toString(), endtime.toString(), str);
System.out.println(str);
str = "";
} else {
System.out.println("No Gap Seen");
}
}
}
}
The exception.
Exception thrown:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.LinkedHashMap.newNode(LinkedHashMap.java:256)
at java.util.HashMap.putVal(HashMap.java:630)
at java.util.HashMap.put(HashMap.java:611)
at sun.util.resources.OpenListResourceBundle.loadLookup(OpenListResourceBundle.java:146)
at sun.util.resources.OpenListResourceBundle.loadLookupTablesIfNecessary(OpenListResourceBundle.java:128)
at sun.util.resources.OpenListResourceBundle.handleKeySet(OpenListResourceBundle.java:96)
at java.util.ResourceBundle.containsKey(ResourceBundle.java:1807)
at sun.util.locale.provider.LocaleResources.getTimeZoneNames(LocaleResources.java:262)
at sun.util.locale.provider.TimeZoneNameProviderImpl.getDisplayNameArray(TimeZoneNameProviderImpl.java:122)
at sun.util.locale.provider.TimeZoneNameProviderImpl.getDisplayName(TimeZoneNameProviderImpl.java:98)
at sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter.getName(TimeZoneNameUtility.java:325)
at sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter.getObject(TimeZoneNameUtility.java:281)
at sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter.getObject(TimeZoneNameUtility.java:267)
at sun.util.locale.provider.LocaleServiceProviderPool.getLocalizedObjectImpl(LocaleServiceProviderPool.java:281)
at sun.util.locale.provider.LocaleServiceProviderPool.getLocalizedObject(LocaleServiceProviderPool.java:265)
at sun.util.locale.provider.TimeZoneNameUtility.retrieveDisplayName(TimeZoneNameUtility.java:135)
at java.util.TimeZone.getDisplayName(TimeZone.java:400)
at java.util.Date.toString(Date.java:1045)
at java.lang.String.valueOf(String.java:2982)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.test.perf.testpgm.main(testpgm.java:112)
Seems like here is the Problem.
for (long j = mincollectiontime; j <= maxcollectiontime; j = j + timeintreval)
You are definitely ruling out the maximum lengh and giving a call in the function. Please post more code so that, specific problem can be noticed.
May be this issue is not related to string concationation, I think this issue with Heap size. Once increase the heap size of your IDE and run the program.

ArrayIndexOutOfBoundsException when splitting the line of a text file

I'm trying to spit this text file:
asdf;asdf;asdf;N/A;N/A;N/A;N/A;N/A;N/A;N/A;N/A
Just so you know. there is no empty line at the bottom of it. That's all there is.
The piece of code that does this job is this.
try{
s = fIN.readLine();
while(s != null){
Parts = s.split(";");
NameFile = Parts[0];
IngredientFile[1] = Parts[1];
QuantityFile[1] = Parts[2];
IngredientFile[2] = Parts[3];
QuantityFile[2] = Parts[4];
IngredientFile[3] = Parts[5];
QuantityFile[3] = Parts[6];
IngredientFile[4] = Parts[7];
QuantityFile[4] = Parts[8];
IngredientFile[5] = Parts[9];
QuantityFile[5] = Parts[10];
list1.add(NameFile + "\n");
for(i=1; i<6; i++){
list1.add(" " + IngredientFile[i] + "" + QuantityFile[i] + "\n");
}
s = fIN.readLine();
}
}catch(IOException e){
list1.add(" ERROR READING FILE. \n");
}
It's throwing the error ArrayIndexOutOfBoundsException: 1 on line 45 which is this
IngredientFile[1] = Parts[1];
Apparently it's the Parts array which is giving me this but that can't be right because I declared it with the size of 1000 just for safety.
public String[] Parts = new String[1000];
Anyone have any ideas what's going on?
You should check the length of Parts before making assignments to make sure it split correctly or throw an exception if not. In your case, the line probably didn't have any ";" separator.
also, you could eliminate the case where you have an empty line or some weird characters.
if (!s.isEmpty() && !s.trim().equals("") && !s.trim().equals("\n")){
//split
}

How to remove whitespace in String imported from Excel

I need to remove all white character from a string and I am not able to do so.
Anyone has an idea on how to do it?
Here is my string retrieved from an excel file via jxl API :
"Destination à gauche"
And here are its bytes :
6810111511610511097116105111110-96-32321039711799104101
There is the code I use to remove whitespaces :
public static void checkEntetes(Workbook book) {
String sheetName = "mysheet";
System.out.print(sheetName + " : ");
for(int i = 0; i < getColumnMax(book.getSheet(sheetName)); i++) {
String elementTrouve = book.getSheet(sheetName).getCell(i, 0).getContents();
String fileEntete = new String(elementTrouve.getBytes()).replaceAll("\\s+","");
System.out.println("\t" + elementTrouve + ", " + bytesArrayToString(elementTrouve.getBytes()));
System.out.println("\t" + fileEntete + ", " + bytesArrayToString(fileEntete.getBytes()));
}
System.out.println();
}
And this outputs :
"Destination à gauche", 6810111511610511097116105111110-96-32321039711799104101
"Destination àgauche", 6810111511610511097116105111110-96-321039711799104101
I even tried to make it myself and it still leaves a space before the 'à' char.
public static String removeWhiteChars(String s) {
String retour = "";
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(c != (char) ' ') {
retour += c;
}
}
return retour;
}
regular expressions to the rescue:
str = str.replaceAll("\\s+", "")
will remove any sequence of whitespace characters. for example:
String input = "Destination à gauche";
String output = input.replaceAll("\\s+","");
System.out.println("output is \""+output+"\"");
outputs Destinationàgauche
if youre starting point is indeed the raw bytes (byte[]) you will first need to make them into a String:
byte[] inputData = //get from somewhere
String stringBefore = new String(inputData, Charset.forName("UTF-8")); //you need to know the encoding
String withoutSpaces = stringBefore.replaceAll("\\s+","");
byte[] outputData = withoutSpaces.getBytes(Charset.forName("UTF-8"));
If you would like to use a formula, the TRIM function will do exactly what you're looking for:
+----+------------+---------------------+
| | A | B |
+----+------------+---------------------+
| 1 | =TRIM(B1) | value to trim here |
+----+------------+---------------------+
So to do the whole column.
1) Insert a column
2) Insert TRIM function pointed at cell you are trying to correct.
3) Copy formula down the page
4) Copy inserted column
5) Paste as "Values"
Reference: Question number 9578397 on stackoverflow.com

Get the Beginning Position Of a field

Hi Guys I am writing a code that reads a text file in this format:
City |First Name| Second Name|Last Name|
The output I currently have is :
Column 1 is 17--------City
Column 2 is 10--------First Name
Column 3 is 12--------Second Name
Column 4 is 9---------Last Name
I need the Begin Position Also Of each Field in the Text File for example:
Column 1 is 17--------City : Position 1
Column 2 is 10--------First Name: Position 18
Column 3 is 12--------Second Name: Position 31
Column 4 is 9---------Last Name: Position 44
Here Is the Code I currently Have. Is there a way to achieve This?
package stanley.column.reader;
import java.io.*;
public class StanleyColumnReader {
public static void main(String[] args) throws IOException {
System.out.println("Developed By Stanley Mungai");
File f = new File("C:/File/");
if (!f.exists()) {
f.createNewFile();
} else {
f.delete();
}
String [] files = f.list();
for (int j = 0; j < files.length; j++){
FileInputStream fs = new FileInputStream("C:/File/" + files[j]);
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
String result = "_result";
BufferedWriter is = new BufferedWriter(new FileWriter("C:/File/" + files[j] + result + ".txt"));
for (int i = 0; i < 0; i++) {
br.readLine();
}
String line = br.readLine();
String[] split = line.split("|");
for (int i = 0; i < split.length; i++) {
int k = i + 1;
System.out.println("Calculating the size of field " + k );
is.write("Column " + k + " is " + split[i].length());
is.flush();
is.newLine();
}
}
System.out.println("Success");
System.out.println("Output Saved to C:/File");
}
}
You could do that with a bit more advanced regexp group matching and get the group start index. But might be overkill and too advanced considering the question.
But a quick simple way in your case that might work is to just use indexOf on the line.
That is change your output to include:
" Position "+(line.indexOf(split[i])+1)
As long as a last name, first name and city aren't repeated on the same line...
You hardly need to flush on each line by the way, I suggest to move it outside the loop.
The regexp solution:
//first declare the pattern once in the class
static final Pattern pattern = Pattern.compile("\\s*(.*?)\\s*\\|");
...
//instead of the split loop:
String line = "City |First Name| Second Name|Last Name| Foo |Bar |"; //br.readLine();
Matcher matcher = pattern.matcher(line);
int column = 1;
while (matcher.find(column == 1 ? 0 : matcher.end())) {
String match = matcher.group(1);
System.out.println("Column " + column + " is " + match.length() + "---" + match + ": Position " + (matcher.start() + 1));
column++;
}
Possibly, depending on the exact position you want, you might want to change (matcher.start()+1) to (matcher.start(1)+1)
IS this an assignment? Please tag it properly.
You haven't said whether the delimiters are "|" in the data too but seeing your code, I am assuming it is.
What I don't understand is how the position you mentioned for Column 3 is 31 and column 4 is 44? Column 3 should be 10+17+1 =28 and column 4 should be 10+17+12+1=40. If I am getting it wrong, you need to post your original data too.
String[] split = line.split("|");
int pos=1; //initial position
for (int i = 0; i < split.length; i++) {
System.out.println("Calculating the size of field " + (i+1));
is.write("Column " + (i+1) + " is " + pos+" : Position "+pos);
pos=pos+split[i].length+1; //starting position for next column data
is.flush();
is.newLine();
}
Or you could find position by using indexOf method : line.indexOf(split[i])+1
If I understand what you need. Maybe you can use the indexOf method. This brings you the first coincidence. After finding this, change the pipe for something different and call indexOf pipe in the next iteration again.
String line = br.readLine();
for (int i = 0; i < split.length; i++) {
System.out.println("Calculating the position " + line.indexOf("|") );
line[line.indexOf("|")] = ",";
}

Categories

Resources