This week's book giveaway is in the Programmer Certification forum.
We're giving away four copies of OCP Oracle Certified Professional Java SE 11 Programmer I Study Guide: Exam 1Z0-815 and have Jeanne Boyarsky & Scott Selikoff on-line!
See this thread for details.
Win a copy of OCP Oracle Certified Professional Java SE 11 Programmer I Study Guide: Exam 1Z0-815 this week in the Programmer Certification forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Junilu Lacar
  • Jeanne Boyarsky
  • Bear Bibeault
Sheriffs:
  • Knute Snortum
  • Devaka Cooray
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Ron McLeod
  • Carey Brown
Bartenders:
  • Paweł Baczyński
  • Piet Souris
  • Vijitha Kumara

StringBuffer -> String -> Array

 
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey, guys!

I've got a small HTTP Post/get app, that returns data in the following format:

[ "Dec 13, 2017 9:00:00 PM", "1769", "LASTNAME, FIRSTNAME", "AB4536", "A", "Z-P11", "COMMENTED", 11, "ABC", "", "32156789", 3241684 ], [ "Jun 02, 2017 1:00:00 AM", "6584", "LASTNAME, FIRSTNAME", "1234", "A", "Z2A", "COMMENTED", 3, "ABC", "RETURN", "5648213897", 65465465 ]

You may notice that the data is presented in blocks of information enclosed within the [ ... ].
I do not know how many of these blocks there will be in the response from the server, it could be one, it could be 10.

So, first I have to determine how many blocks I got, then I have to extract certain elements from these blocks, for example these from each block if there's more than one - "Dec 13, 2017 9:00:00 PM", "LASTNAME, FIRSTNAME" and let's say this one "COMMENTED".


The data is returned as a String type from StringBuffer.
How should I approach this? Should I turn this into array (is it possible?) or should I just manipulate the string itself, using regular expressions? But how can you determine how many blocks you got with a string? Truncate string at '], [' ?
And then how are you gonna find the required elements in the string? It looks like an array is the best way to go.

Here's a code snippet. I'm really freakin new to this, so please don't give too vague of an answer.
Thanks!)))

 
Rancher
Posts: 2179
15
Android Java ME Eclipse IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You may split it based on ]

 
oroszCapa Blaszczekievicz
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, that's great. Thanks, man!

Now I have a string array that has n amount of blocks. What do you think is the best way to extract data within quotes " " from these blocks?

I tried doing this:



But the a mount of array items in arr[] is variable, and if I put this expression in a loop, to cycle through all the items in arr[], it isn't working.
 
Swastik Dey
Rancher
Posts: 2179
15
Android Java ME Eclipse IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
 
Sheriff
Posts: 6378
172
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm not sure that's going to work properly.  There is an element

   "LASTNAME, FIRSTNAME"

that should be all one element and not be split by the comma.  I would look into using a CSV library like

http://commons.apache.org/proper/commons-csv/
 
oroszCapa Blaszczekievicz
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Knute Snortum wrote:I'm not sure that's going to work properly.  There is an element

   "LASTNAME, FIRSTNAME"

that should be all one element and not be split by the comma.  I would look into using a CSV library like

http://commons.apache.org/proper/commons-csv/



Yeah, that one is easily fixed by changing   to
 
Marshal
Posts: 14388
240
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I agree with Knute. Once you start having to fiddle around with regex to find matches for special cases, it's probably better to turn to an existing library that has been tested, like the Apache Commons CSV.

Jamie Zawinski wrote:Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

 
Marshal
Posts: 66261
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Swastik Dey wrote:You may split it based on ] . . .

But isn't ] a regex metacharacter? Would't you have to use "\\]" as a regex?
 
Knute Snortum
Sheriff
Posts: 6378
172
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It is, but evidently the pattern matching engine knows that it's only meta when it first encounters a "[" character.  So the regex will work.
 
Bartender
Posts: 3611
151
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I got an error when using the regex "],\\s+[".

I don't know these csv readers, but processing that inputbuffer is not difficult. It is just a little laborious.
For instance (like Swastik proposed)
 
Knute Snortum
Sheriff
Posts: 6378
172
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Piet, I believe your solution still splits the LASTNAME, FIRSTNAME and DATE when it shouldn't.  Didn't test though.

I spent entirely too much time on this, but I think my solution2() works well.  You could strip off the quotes if needed, but I didn't.  solution1() is the original solution.  solution3() is where I tried to use Apache Commons CSV, but I couldn't get it to work.
 
Campbell Ritchie
Marshal
Posts: 66261
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Knute Snortum wrote:. . . . So the regex will work.

Never knew that; thank you.
 
Piet Souris
Bartender
Posts: 3611
151
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi Knute,

indeed are FIRSTNAME and LASTNAME split, just like the date in the beginning (since it contains a comma too). But that is not a problem. The indices are known, so you can say "LocalDate date = LocalDate.of(s[0] + s[1]) (with a suitable DateFormatter) and likewise String name = s[6] + ", " + s[7], and maybe some other conversions. It is just a bit laborious. I can never remember how regexes work, always have to read again Oracle's tutorial, and your code is very new to me. Got some study to do here, and thanks for such an example.
 
oroszCapa Blaszczekievicz
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you guys a lot for your input!

Here's my ugly code. The surprising thing is that it works.
I get clean entries in the ArrayList and in the end, using nested loops I get 2D string array, which is what I need exactly to feed it to the JTable in Swing. Hooray!

If you see something too ugly, which could be refactored, please do chip in!

 
oroszCapa Blaszczekievicz
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Ok, I think I need your help here))
I guess celebrations and patting myself on the back that was a bit premature))

The code I said was working, was actually tested with sample lines of data (you can see in the original post) and in an online java editor (JDOODLE). Now when I threw that code into the real world app and into the Eclipse, the real world app kicked me in the balls.

Here's the data received (already cleaned by cutting the first 12 characters and the last 172):

[      "Jun 19, 2017 4:00:00 AM",      "M1145",      "LASTNAME,NAME MR",      "ZP6411",      "X",      "P-I10",      "FOUND\nPRESENT/NST/PL JT",      3,      "TWA",      "COMMENTED",      "347637463",      458720485    ]

I call this a "block", it contains 12 elements. These "blocks" of 12 elements are gonna be included in the 2D string array[blocks][12]

Now this is what ended up in the array:

Jun 19, 2017 4:00:00 AM

M1145

LASTNAME,NAME MR

ZP6411

X

P-I10


Only half of the data is saved, and it looks like it saves a bunch of white spaces, instead of the payload. There must be something wrong with the nested loop that creates the 2D array. Could you please check the damn thing and see if it's correct? Thank you!
I added comments to the code, so the loop is easier to find.
[UPDATE]: It is probably a split and remove part that is not working correctly, please see the next post, thank you!



 
oroszCapa Blaszczekievicz
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, I guess it's not the loop.
This is what I get right after all the split and remove functions.

[      ,  Jun 19, 2017 4:00:00 AM,       , M1145,       , LASTNAME,NAME MR,       , ZP6411,       , X,       , P-I10,       , FOUND\nPRESENT/NST/PL JT,       3,      , TWA,       ,       , 347637463,       458720485   ]

And the original line:

[      "Jun 19, 2017 4:00:00 AM",      "M1145",      "LASTNAME,NAME MR",      "ZP6411",      "X",      "P-I10",      "FOUND\nPRESENT/NST/PL JT",      3,      "TWA",      "COMMENTED",      "347637463",      458720485    ]

 
Knute Snortum
Sheriff
Posts: 6378
172
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let's back up.

If the data is formatted the way you have just posted, you need to do the following:

1) Strip off the "[" and "]"
2) Split by commas *
3) Remove quotes

How would you go about doing this?

* You'll have to reconstruct fields like the date and the name.
 
oroszCapa Blaszczekievicz
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, Knute! Really appreciate you taking the time to help me. Thanks a lot!

I've been reading,googling and thinking about this so much recently that what's inside my head is a mess right now, and I lost that fragile and delusive structure of knowledge I had on the subject)) I'm not even sure I understand now what OOP is all about.
Anyway.

> How would you go about doing this?

Well, first we split the string at "]" to get blocks. The so called 12 element "original line" from my latest post. Simultaneously we populate a String array.


Then we split it by commas adding the elements to a String ArrayList:


Finally we use ArrayList.removeIf to get rid of the quotes:


Now as to reconstructing the fields... this gives me nightmares, I don't think I'm ready for this yet.

I was thinking of something along the lines of:


Repeat for other blocks and do the same with the names.


Sorry for the sordid attempt))
 
Saloon Keeper
Posts: 6423
61
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Most people hate this but I'm going to offer it up anyway because it works. Regular expressions and other lexars generate state machines behind the scenes, this one is just unrolled.
 
Piet Souris
Bartender
Posts: 3611
151
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In my reply I suggested to use a dedicated class to collect all the fields of a block, and I suggested to converse some strings of a block into more useful types. For instance, if, after splitting a block, we have the fields f1 = "Dec 17" and f2 = "2019 9:00:00 PM", then we can put these into a useful LocalDateTime, with a suitable DateTimeFormatter. I did not tell how that could be done, but here is a way

With this, we can get:
 
oroszCapa Blaszczekievicz
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Piet Souris wrote:In my reply I suggested to use a dedicated class to collect all the fields of a block, and I suggested to converse some strings of a block into more useful types. For instance, if, after splitting a block, we have the fields f1 = "Dec 17" and f2 = "2019 9:00:00 PM", then we can put these into a useful LocalDateTime, with a suitable DateTimeFormatter. I did not tell how that could be done, but here is a way

With this, we can get:



Looks interesting, thanks!
 
oroszCapa Blaszczekievicz
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Carey Brown wrote:Most people hate this but I'm going to offer it up anyway because it works. Regular expressions and other lexars generate state machines behind the scenes, this one is just unrolled.



I think I got it to work (fingers crossed), now to the next stages of making this app happen. Stay tuned for more questions)))
 
Carey Brown
Saloon Keeper
Posts: 6423
61
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

...because it works...

Famous last words. Well, for your use I think it should work but I found and fixed some edge cases. Here's an update.
 
Yup, yup, yup. Tiny ad:
Java file APIs (DOC, XLS, PDF, and many more)
https://products.aspose.com/total/java
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!