JavaFX splitting Clipboard getString() strange behavior - java

I made a program using JavaFX where I have to paste into an excel like table.
I followed some tutorials online but noticed strange behavior in the way the paste code functions. After a while, I isolated the problem to the following code.
public void handlePaste() {
Clipboard clipboard = Clipboard.getSystemClipboard();
if (clipboard.hasString()) {
//start from the point that has focus
// abort if there's not cell selected to start with
if (getSelectionModel().getSelectedCells().size() == 0) {
return;
}
// get the cell position to start with
TablePosition pasteCellPosition = getFocusModel().getFocusedCell();
String pasteString = Clipboard.getSystemClipboard().getString();
int rowClipboard = -1;
Iterable<String> rowStrings = Splitter.on("\n").omitEmptyStrings().split(pasteString);
System.out.println("Print Rows");
for (String rowString : rowStrings) {
System.out.println(rowString);
System.out.println(rowString + " printing again");
}
for (String rowString : rowStrings) {
rowClipboard++;
Iterable<String> columnStrings = Splitter.on("\t").split(rowString);
int colClipboard = -1;
System.out.println("Printing Columns");
for (String columnString : columnStrings) {
System.out.println(columnString);
System.out.println(columnString + " printing again");
}
}
}
}
I use the output statement to demonstrate the problem.
Basically, I'm splitting the contents of the string based off and '\n' and '\t' characters.
The problem is whenever I try to do anything with the split strings, the string just...DISAPPEARS...
The output statements I put in demonstrate this.
Suppose the string on the clipboard is
l a
l b
l c
Then the expected output should be
Print rows
l a
l a printing again
l b
l b printing again
r c
r c printing again
Printing Columns
l
l again
a
a again
l
l again
b
b again
r
r again
c
c again
But the output ends up being
Print rows
l a
printing again
l b
printing again
r c
printing again
Printing Columns
l
again
a
again
l
again
b
again
r
again
c
again
Notice how when I try to append " printing again" to the split string, I'm simply getting blank strings.
I tried fixing the issue by using substring, and by using the standard java string splitting methods and I got the same behavior.
Finally, to fix it, I just used the java.awt Clipboard instead of the JavaFX clipboard and suddenly...it worked!
java.awt.Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit();
java.awt.datatransfer.Clipboard awtClipboard = toolkit.getSystemClipboard();
try {
pasteString = (String) awtClipboard.getData(java.awt.datatransfer.DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException ex) {
} catch (IOException ex) {
}
Using the above line of code to get the pasteString instead of the JavaFX clipboard fixed the problem, and now I get the expected behavior and output.
For now, I will stick with the above fix, but it seems strange that the JavaFX clipboard is producing this behavior when the awt clipboard does not. Can anybody explain why this is happening? Is this a bug with the JavaFX clipboard?

LuxxMiner's comment above appears to offer a solution.
Using System.lineSeparator() also seems to work fine.

Unfortunately I found the above solutions didn't quite work out for me. The problem is that while the system seperator does get me the seperator for my systems, when I copy and paste from another program, it isn't guaranteed that the program I'm copying from is using the systems' seperator. For instance, when I copied from an excel spreadsheet, I kept getting the same strange behavior I got before, and I believe it was because excel didn't use the systems seperator.
So this is the solution I eventually came upon...
Basically it looks for ANY of the basic line seperators and splits on them.
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
Iterable<String> rowStrings = Splitter.on(CharMatcher.anyOf("\n\r")).omitEmptyStrings().split(pasteString);

Related

Method count words in a file

Hi guys I'm writing a method which counts words in a file, but apparently there is a mistake somewhere in the code and the method does not work. Here's my code:
public class Main2 {
public static void main(String[] args) {
count("/home/bruno/Desktop/WAR_JEE_S_09_Podstawy/MojPlik");
}
static int count(String fileName){
Path path = Paths.get(fileName);
int ilosc = 0;
String wyjscie = "";
try {
for (String charakter : Files.readAllLines(path)){
wyjscie += charakter;
}
StringTokenizer token = new StringTokenizer(wyjscie," \n");
} catch (IOException e) {
e.printStackTrace();
}
return ilosc;
}
}
The file path is correct, here is the file content
test test
test
test
after i call the method in main it displays nothing. Where is the mistake ?
Your code would count lines in a file ... well, if you followed up on that thought.
Right ow your code is simply reading lines, putting them into one large string, to then do nothing about the result of that operation. You have a single int counter ... who is init'ed to 0, and then just returned without ever being used/increased! And unless I am mistaken, readAllLines() will automatically remove the newline char in the end, so overall, your code is nothing but useless.
To count words you have to take each line and (for example) split that one-line-string for spaces. That gives you a number. Then add up these numbers.
Long story short: the real answer here is that you should step back. Don't just write code, assuming that this will magically solve the problem. Instead: first think up a strategy (algorithm) that solves the problem. Write down the algorithm ideas using a pen and paper. Then "manually" run the algorithm on some sample data. Then, in the end, turn the algorithm into code.
Also, beside that you does not output anything, there is a slight error behind you logic. I have made a few changes here and there to get your code working.
s.trim() removes any leading and trainling whitespace, and trimmed.split("\\s+") splits the string at any whitespace character, including spaces.
static int count(String fileName) throws IOException {
Path path = Paths.get(fileName);
int count = 0;
List<String> lines = Files.readAllLines(path);
for (String s : lines) {
String trimmed = s.trim();
count += trimmed.isEmpty() ? 0 : trimmed.split("\\s+").length;
}
return count;
}
Here is the code using functional-style programming in Java 8. This is also a common example of using Stream's flatMap - may be used for counting or printing words from a file.
long n = Files.lines(Paths.get("test.txt"))
.flatMap(s -> Stream.of(s.split("\\s+")))
.count();
System.out.println("No. of words: " + n);
Note the Files.lines(Path) returns a Stream<String> which has the lines from the input file. This method is similar to readAllLines, but returns a stream instead of a List.

How to print an array list (that's using char) in a JTextArea?

Okay, so I have to make a game for school that's called "Angry Tanks" it's basically a simpler version of Angry Birds.
We have to read in a textfile to use as a landscape for our game, this text file contais spaces and hashtags, the hastags represent the land.
The file has bean read and inserted into an arraylist, there is a public method calles getLandscapeFromFile().
I am trying to print the landscape into a JTextArea called textArea, using a loop that replaces all the hashtags with an image. Am I supposed to use a textArea or should another panel be used?
This is the code I've tried but doesn't work:
for (int i = 0; i < Landscape.getLandscapeFromFile().size(); i++) {
for (char[] c : Landscape.getLandscapeFromFile()) {
textArea.append(String.valueOf(c[i]));
}
}
I've been trying all sort of stuff, but nothing seems to work...
And by the way, I'm not very good at Java, this is only my first year studying IT.
The problem is in your second loop
You select i char of word
for (char[] c : Landscape.getLandscapeFromFile()) {
textArea.append(String.valueOf(c[i]));
}
You probably wonted to write each character of that array.
for (char[] c : Landscape.getLandscapeFromFile()) {
textArea.append(String.valueOf(c));
}
As you task is to write the content form File to textArea you should do this.
TIP: You should avoid to access the loading method twice as it can time consuming user a local variable.
List<char[]> landscapes = Landscape.getLandscapeFromFile(); //Read once
for(char[] landscape : landscapes) {//Iterate through all landscapes
stextArea.append(new String(landscape)); //Create new String for char array
}
You can use a StringBuilder:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Landscape.getLandscapeFromFile().size(); i++) {
for (char[] c : Landscape.getLandscapeFromFile()) {
sb.append(String.valueOf(c));
}
}
textArea.setText(sb.toString());

Posting from apple clipboard into JTable?

I would like to paste multiple cells from excel into JTable. Searching for the solution returned this old reference:
I used this ExcelAdapter.java with a couple of minor changes as I wanted it to work on Mac and not only on PC. So, I had to use that.
KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C,KeyEvent.META_DOWN_MASK);
When OS is Mac and also I found out that while copying, the new line character should be \r and not \n.
There is an interesting discussion on the subject
here.
So, now copying from JTable into excel works fine, but with pasting I have the following problem:
The starting cell where I want to paste gets active for editing once I press the Command Key, so when I press V the content from the clipboard does not write into that starting cell.
So, all other cells are filled fine, but not the first one. Here is the relevant snippets of the code.
public final static boolean SYSTEMISMAC=(System.getProperty("os.name")).startsWith("M");
....
if(SYSTEMISMAC) StringTokenizer st1=new StringTokenizer(trstring,"\r"); // For Mac
else StringTokenizer st1=new StringTokenizer(trstring,"\n");
for(int i=0;st1.hasMoreTokens();i++)
{
rowstring=st1.nextToken();
StringTokenizer st2=new StringTokenizer(rowstring,"\t");
for(int j=0;st2.hasMoreTokens();j++)
{
value=(String)st2.nextToken();
if (startRow+i< jTable1.getRowCount() &&
startCol+j< jTable1.getColumnCount())
jTable1.setValueAt(value,startRow+i,startCol+j);
System.out.println("Putting "+ value+" atrow= "+startRow+i+"column= "+startCol+j);
}
}
I can see that the program tries to get the value into the table when i=0 and j=0, but it cannot (I am guessing because the cell is already active). How to get over it?
Should I disable the activation of the cell by pressing Command (I don't think it is that useful, the user can use the mouse to select a cell, but how to disable)? I am not sure whether this problem is Mac specific (I have not checked Windows yet). If there is a better way of pasting from excel to JTable?
Just to summarize, as correctly pointed out by MadProgrammer, the key is to call Cell Editor and cancel any editing.
For completeness I am providing corrected snippet of the code with the corrections. It works for me
public final static boolean SYSTEMISMAC=(System.getProperty("os.name")).startsWith("M"); if(SYSTEMISMAC) StringTokenizer st1=new StringTokenizer(trstring,"\r"); // For Mac
else StringTokenizer st1=new StringTokenizer(trstring,"\n");
CellEditor cellEdit=jTable1.getCellEditor(startRow, startCol);
cellEdit.cancelCellEditing();
for(int i=0;st1.hasMoreTokens();i++)
{
rowstring=st1.nextToken();
StringTokenizer st2=new StringTokenizer(rowstring,"\t");
for(int j=0;st2.hasMoreTokens();j++)
{
value=(String)st2.nextToken();
if (startRow+i< jTable1.getRowCount() &&
startCol+j< jTable1.getColumnCount())
jTable1.setValueAt(value,startRow+i,startCol+j);
System.out.println("Putting "+ value+" atrow= "+startRow+i+"column= "+startCol+j);
}
}
I had better luck with this variant on your solution. By using both \n and \r as tokenisers on line 3 below I can paste from excel or from other sources like TextEdit.
The rowstring.replace on line 7 also allows me to carry over empty cells in a two-dimensional table from excel.
Keeping in mind that on Mac, I still have to copy and paste with control + C, control + P, not command + C, command + P
String trstring= (String)(system.getContents(this).getTransferData(DataFlavor.stringFlavor));
System.out.println("String is:"+trstring);
StringTokenizer st1=new StringTokenizer(trstring,"\n\r");
for(int i=0;st1.hasMoreTokens();i++)
{
rowstring=st1.nextToken();
rowstring = rowstring.replace("\t\t", "\t \t");
StringTokenizer st2=new StringTokenizer(rowstring,"\t");
for(int j=0;st2.hasMoreTokens();j++)
{
value=(String)st2.nextToken();
if (startRow+i< jTable1.getRowCount() &&
startCol+j< jTable1.getColumnCount())
jTable1.setValueAt(value,startRow+i,startCol+j);
System.out.println("Putting "+ value+"atrow="+startRow+i+"column="+startCol+j);
}
}

String Input (Only outputs the first word said)

I'm trying to make a piece of code that will yell out anything I input.
So the command is 'yell'
I want to be able to type 'yell (whatever i want here)' and it will yell it out. I've managed to get this working with a help of a friend. But for some reason it will only yell the first word that's been output. So I can't type a sentence because it will only say the first word of a sentence.
Here's the piece of code, I hope you can help.
case "npcyell":
for (NPC n : World.getNPCs()) {
if (n != null && Utils.getDistance(player, n) < 9) {
String sentence = "";
for (int i = 1; i < cmd.length; i++) {
sentence = sentence + " " + cmd[i];
}
n.setNextForceTalk(new ForceTalk("[Alert] "
+ Utils.getFormatedMessage(sentence)));
}
}
return true;
Well I did something similar a while ago. You said that you wanted to be able to say "yell(text)" and have it output whatever the text was. I have a different way of implementing it than you do, but the general result is the same, but it can be adapted to however you are using it in this context. This is also assuming that you are running this program as a console project only. if not change the scanner with whatever you are using to input text into and replace the text assignment to text = textInputArea.getText().toString(); and change the output statement to System.out.println(text.getText().toString().substring(6,text.getText().toString().length() - 1));
Scanner s = new Scanner(System.in);
String text = s.nextLine();
if (text.startsWith("yell(") && text.endsWith(")")){
System.out.println(text.substring(6,text.length() - 1));
}
I hope this works for you. And I honestly hope that this is adaptable towards the program you are making.

java System.out.println() strange behavior long string

Can somebody explain me why this code does not print the numbers?
String text = new String("SomeString");
for (int i=0; i<1500; i++) {
text = text.concat(i+"");
}
System.out.println(text);
Result
SomeString
If I lower the number of runs to 1000 it works, why?!
And also if I add not only a number but also a character, it works.
Ok New Update:
Thanks for the code examples. I tried them all but what I found out is, that the console
actually display the numbers but only in fontcolor white. But the first part of the String
SomeString is black.
I use jdk1.7.0_06 !
This is eclipse bug. Fixed width console fixes the output.
String.concat() accepts a String parameter.
If you add "a number and a character" you are adding a string because the + operator understands you are chaining String and numeric data.
Anyway code runs fine to me, numbers appended till 1499 as expected.
There are a couple things you could try. I'll give you an example of both.
First, in Java you can simply add strings together. Primitives such as int should be automatically converted:
String text = new String("SomeString");
for (int i = 0; i < 1500; i++) {
text += i;
}
System.out.println(text);
Second, if the first method still isn't working for you then you can try to explicitly convert your int to a String like so:
String text = new String("SomeString");
for (int i = 0; i < 1500; i++) {
text += Integer.toString(i);
}
System.out.println(text);
To do the same more efficiently
StringBuilder text = new StringBuilder("SomeString");
for (int i = 0; i < 1500; i++) {
text.append(i);
}
System.out.println(text);
Both examples work for me on Java 6 update 32 and Java 7 update 3.
Woah, this is weird. I got the same result. At first glance, it looks like a bug in the JVM, but I tried running the program from the command-line and it works fine. It must be a bug in the Eclipse console. I found that changing the console to have a fixed width solves the display issue.
I also found that if you replace i + "" with i + "," it displays fine. It seems there's something Eclipse console doesn't like about having a long continuous stretch of pure numbers.
String text = "SomeString";
for (int i = 0; i < 15000; i++) {
// text = text.concat(i + ""); // Doesn't display correctly
// text += i; // Doesn't display correctly
text = text.concat(i + ","); // Displays correctly
// text += i + ","; // Displays correctly
}
System.out.println(text);
This bug is somewhat worrying to me. Good find!
UPDATE: I tried just printing a long line of "xxxxxx" and found that up to 32000 characters are displayed correctly. When the line goes to 32001 it's not displayed. When I put "12345" + "xxxxxxxxx...", I was still able to display 32000 "x" characters which means the line length is longer than 32000, so it's nothing to do with total line length. It seems that it's to do with the length of parts of String objects.

Categories

Resources