Im parsing HTML code from a site and I'm nearly done. I have the section of text i need from the site, but occasionally there are some links included in the HTMl that i wish to get rid of. I am thinking of using the fact that all of the elements I do not want start with '<' and of course and with '>'. Is there anyway to do this? This is what I have so far.
for(int i = 0; i<desc.length();i++)
{
if(desc.charAt(i)==('<')){
}
}
desc being the string i want to trim up.
It's generally considered a bad idea to parse markup languages like XML and HTML manually. However, if you are only trying to remove all the elements, I could see where a simple script may be useful.
Something I thought worth mentioning, is that if you remove all elements of the HTML, you may have several pieces of text jammed together. Check out this piece of code, see if it helps.
public class RemoveHtmlElements {
public static void main(String[] args) {
String html = "<!DOCTYPE html><html><body><h1>My First Heading</h1>"
+ "<p>My first paragraph.</p></body></html>";
boolean elementsExist = true;
while(elementsExist) {
if(html.contains("<")) {
int open = html.indexOf("<");
int closed = html.indexOf(">", open);
html = html.substring(0, open) + " " + html.substring(closed + 1);
} else {
elementsExist = false;
}
}
System.out.println(html);
}
}
This should clean HTML of any bracketed elements. It will input a space where it removes an element to keep text from being jammed together unexpectedly.
I would try something like this;
StringBuilder sb = new StringBuilder();
boolean open = false;
for (char c : desc.toCharArray()) { // iterate over the characters
if (c == '<') { // if we hit a less then store that the tag is open.
open = true;
} else if (open && c == '>') { // if the tag is open and the close symbol hits close.
open = false;
} else if (!open) { // if the tag isn't open
sb.append(c);
}
}
System.out.println(sb.toString()); // print the string.
Related
public static ArrayList<String> cleanUpUrls(ArrayList<String> oldList,String url) {
ArrayList<String> cleanedList = new ArrayList<String>();
for (int i =0; i <oldList.size(); i++) {
boolean isAnchorLink = false;
String link = oldList.get(i);
link = link.toLowerCase();
//clean href="" part
link = link.substring(link.indexOf("\"") + 1);
link = link.substring(0, link.indexOf("\""));
//check if anchor link
if (link.charAt(0) == '#') {
isAnchorLink = true;
}
//relative to absolute
if (link.charAt(0) == '/') {
link = url.concat(link);
}
//if no http or https then add
if (link.indexOf("http") == -1 && link.indexOf("https") == -1) {
String http = "http://";
link = http.concat(link);
}
//remove query strings
if (link.indexOf("?") != -1) {
link = link.substring(0,link.indexOf("?"));
}
if (!isAnchorLink){
cleanedList.add(link);
}
} System.out.println("xxxx");
return cleanedList;
}
Here is a function cleanUpUrls which takes an arrayList of strings as parameter and removes all anchor links i.e. href ="" part and converts them to absolute links, if they are relative.
The problem is that when I call it, it executes without compile-time/runtime error but does not return expected response. In fact if I print anything after the function call It does not print anything, even the println("xxx"); does not get display. I am not getting any compilation/run-time errors.
You probably have an exception here:
link = link.substring(0, link.indexOf("\""));
since in your example "x" does not contain '\' the second arg will be -1 and will cause substring to throw and exception (IndexOutOfBoundsException).
Since you catch the exception but print nothing, it will look like it runs with no error so put a print code for displaying the exception:
catch (Exception e) {
System.out.println("Exception caught: " + e);
}
I am using a terminal emulator library to create a terminal and then I use it to send the data entered over serial to a serial device. When the data is sent back I want to parse it and show the most important information to the user in an editText. Currently I receive byte arrays/chunks and I convert them to a string. When I get a \r or a \n I crete a new string and the process repeats. This is fine for most commands, however some commands return results over multiple lines like "show vlan" here:
When I loop through this I get a string for each line. The first would contain VLAN Name Status and Ports, as an example. So now I have a problem, how can I VLAN 1 has x ports active. They are in different strings. Here is the code and screenshot for a current easier command where I am interested in one line:
Handler viewHandler = new Handler();
Runnable updateView = new Runnable() {
#Override
public void run() {
mEmulatorView.invalidate();
if (statusBool == true) {
for (int i = 0; i < dataReceived.length(); i++) {
parseCommand = parseCommand + dataReceived.charAt(i);
if (dataReceived.charAt(i) == '\n' || dataReceived.charAt(i) == '\r'){
if(parseCommand.contains("KlasOS"))
{
String[] tokens = parseCommand.split("\\s{1,}");
final String ReceivedText = mReceiveBox.getText().toString() + " "
+ new String("Software Version: " + tokens[1] + "\n" );
runOnUiThread(new Runnable() {
public void run() {
mReceiveBox.setText(ReceivedText);
mReceiveBox.setSelection(ReceivedText.length());
}
});
}
parseCommand = "";
}
}
statusBool = false;
viewHandler.postDelayed(updateView, 1000);
}
}
};
Now I would like to change this so i can deal with multiple lines. Would the ebst way be to store strings if they contain certain information?
I need this outputted on the right hand editText:
"The following ports are on vlan 1: Fa1/0, fa1/1, fa1/2, fa1/3, fa1/4, fa1/5, fa1/6, fa1/7, fa1/8, fa1/9, fa1/10, fa1/11, Gi0"
Basically, you need a way to reliably detect the end of a command result. Then it boils down to sending your command, reading data from the device until you encounter the end of result, and finally parsing that result.
I would scan for the prompt (switch#) as you do in your own answer. Maybe your are even able to force the device to use a more peculiar character sequence, which is unlikely to occur in the regular output of commands and makes it easier to detect the end of a result. For example, you could try to configure the prompt to include a control character like ^G or ^L. Or if your users don't mind, you could always send a second command that emits such a sequence, for example, "show vlan; echo ^G".
You should also be prepared for command errors, which result in a different output, for example, more or fewer lines as expected or a totally different output format. A result may even contain both, a regular output and a warning or an error.
I solved this in a messy way with a boolean and a few strings. i made a method for appending strings.
if((parseCommand.contains("VLAN Name") && parseCommand.contains("Status")&& parseCommand.contains("Ports"))
|| ((ShowVlanAppend.contains("VLAN Name")&& ShowVlanAppend.contains("Status")&& ShowVlanAppend.contains("Ports"))))
{
commandParse();
if(finalCommandBool == true){
runOnUiThread(new Runnable() {
public void run() {
mReceiveBox.setText(finalCommand);
mReceiveBox.setSelection(finalCommand.length());
ShowVlanAppend = "";
finalCommand = "";
finalCommandBool = false;
}
});
}
}
public void commandParse()
{
if (!parseCommand.contains("switch#")){
ShowVlanAppend = ShowVlanAppend + parseCommand;
}
else{
finalCommand = ShowVlanAppend;
finalCommandBool = true;
}
}
I'm looking for a solution to receive text input through LWJGL. I'm not referring to the kind of standard keyboard event input offered by LWJGL, I'm looking for the ability to receive actual lines of text input, much like the TextFields offered by AWT/Swing. I'm doing this mostly in the interest of learning, and as such, I have no interest in using a library outside of LWJGL (such as TWL).
Currently, I have something like this:
private boolean shift = false;
private void chatControls(float ticksPassed) {
while (Keyboard.next()) {
if (Keyboard.isKeyDown(Keyboard.KEY_RETURN)) {
this.ui.toggleChat();
} else if (Keyboard.isKeyDown(Keyboard.KEY_DELETE)) {
this.chatText = "";
} else if (Keyboard.isKeyDown(Keyboard.KEY_BACK) && Keyboard.getEventKeyState()) {
try {
this.chatText = this.chatText.substring(0, chatText.length() - 1);
} catch (StringIndexOutOfBoundsException e) {}
} else if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
shift = Keyboard.getEventKeyState();
} else if (Keyboard.getEventKeyState() && !jtLetter) {
if (shift) {
this.chatText += Character.toUpperCase(Keyboard.getEventCharacter());
} else {
this.chatText += String.valueOf(Keyboard.getEventCharacter());
jtLetter = true;
}
} else {
jtLetter = false;
}
this.ui.updateChat(chatText);
}
}
However, it does not manage to properly handle shift, nor any of the other special commands described above. So, what's the best thing to do?
Take a look at this file of the source code of NiftyGUI, which should contain this text handling code.
Just delete your shift handling line and add:
if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT))
shift=true;
before the beginning of the While loop.
Using stack data structure(s): If the input file is not balanced, the un-balance cause and the in-file localization details will be supplied. For flexibility reasons, read the balancing pairs of symbols from a text file. Test your program by considering the following pairs of symbols: ( ), { }, [ ], /* */
I'm having trouble with the last requirement: /* */
I also can't seem to grasp how to print the in-file localization details? i.e which line number of the text file the error has occured on?
The text file looks like this:
(()(()
{}}}{}{
[[[]][][]
((}})){{]
()
[]
{}
[]{}
()()()[]
*/ /*
(a+b) = c
The code:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class P1 {
private boolean match = true;
// The stack
private java.util.Stack<Character> matchStack = new java.util.Stack<Character>();
// What to do with a match
public boolean ismatch() {
return match && matchStack.isEmpty();
}
// Finding a match
public void add(char c) {
Character k = leftSide(c);
if (k == null)
;
else if (k.charValue() == c)
matchStack.push(k);
else {
if (matchStack.isEmpty() || !matchStack.pop().equals(k))
match = false;
}
}
// Add string values
public void add(String s) {
for (int i = 0; i < s.length(); i++)
add(s.charAt(i));
}
// The various symbol pairs
protected static Character leftSide(char c) {
switch (c) {
case '(':
case ')':
return new Character('(');
case '[':
case ']':
return new Character('[');
case '{':
case '}':
return new Character('{');
default:
return null;
}
}
// Main method. Welcome message, read the test file, build the array, print
// results.
public static void main(String args[]) {
List<String[]> arrays = new ArrayList<String[]>();
// Welcome message
System.out
.println("Project #1\n"
+ "Welcome! The following program ensures both elements of various paired symbols are present.\n"
+ "Test Data will appear below: \n"
+ "-------------------------------");
// Read the file
try {
BufferedReader in = new BufferedReader(new FileReader(
"testfile.txt"));
String str;
// Keep reading while there is still more data
while ((str = in.readLine()) != null) {
// Line by line read & add to array
String arr[] = str.split(" ");
if (arr.length > 0)
arrays.add(arr);
// Let the user know the match status (i.e. print the results)
P1 mp = new P1();
mp.add(str);
System.out.print(mp.ismatch() ? "\nSuccessful Match:\n"
: "\nThis match is not complete:\n");
System.out.println(str);
}
in.close();
// Catch exceptions
} catch (FileNotFoundException e) {
System.out
.println("We're sorry, we are unable to find that file: \n"
+ e.getMessage());
} catch (IOException e) {
System.out
.println("We're sorry, we are unable to read that file: \n"
+ e.getMessage());
}
}
}
An easy way to implement this would be using a map of stacks such as Map<String, Stack<Location>>, where Location is a class you create that holds two ints (a line number and a character number). That can be your location info. The key (String) to this map would be your left side (opener) part of your pairs. Every time you have an opener you look up the appropriate Stack in the map and push a new Location on it for that opener. Each time you encounter a closer you look up its opener, use the opener to look up the correct Stack in the map and then pop it once. The reason I say use String for your key is because not all your openers can be represented by Character namely your /* opener, so a String will have to do. Since you can't switch on Strings for your leftSide(char) (which will now be leftSide(String)) function you'll either have to use if-else or use a map (Map<String, String>) to create the closer to opener mappings.
When the end of the file is reached the only Location objects remaining in the Stack objects should be unclosed openers.
I have written a program to monitor the status of some hard drives attached to a RAID on Linux. Through this program I execute several command line commands. An interesting error occurs though....the program runs for a good three minutes before it seems that it can no longer correctly execute the command it had been previously executing (for many iterations).
It spits out an array index error (my variable driveLetters[d]) because it appears to miss the drive somehow (even though it found it hundreds of times before).
Other things to note...if I tell it to reset int "d" to "0" if it exceeds the number of drives...the program won't crash and instead will just become stuck in an infinite loop.
Also, the time at which the program crashes varies. It doesn't appear to crash after a set number of intervals. Finally, I don't get any kind of memory leak errors.
Here is some of code that should reveal the error:
public static void scsi_generic() throws IOException, InterruptedException
{
int i =0;
int d =0;
int numberOfDrives = 8;
char driveLetters[] = {'b','c','d','e','f','g','h','i','j','k','l','m'};
String drive = "";
while (i <= numberOfDrives)
{
System.out.println("position 1");
List<String> commands = new ArrayList<String>();
commands.add("cat");
commands.add("/sys/class/scsi_generic/sg"+i+"/device/sas_address");
SystemCommandExecutor commandExecutor = new SystemCommandExecutor(commands);
int driveFound = commandExecutor.executeCommand();
if (driveFound == 0)
{
System.out.println("Folder: sg" + i + " was found." );
StringBuilder stdout = commandExecutor.getStandardOutputFromCommand();
String data = stdout.toString();
String sas = data.substring(11,12);
int sasA = Integer.parseInt(sas,16);
boolean matchedSG = false;
while (matchedSG == false)
{
System.out.println("position2");
List<String> lookSD = new ArrayList<String>();
lookSD.add("test");
lookSD.add("-d");
lookSD.add("/sys/class/scsi_generic/sg"+i+"/device/block:sd" + driveLetters[d]);
SystemCommandExecutor commandSearch = new SystemCommandExecutor(lookSD);
int sdFound = commandSearch.executeCommand();
StringBuilder stdout3 = commandSearch.getStandardOutputFromCommand();
StringBuilder stderr = commandSearch.getStandardErrorFromCommand();
String sdFound2 = stdout3.toString();
if (sdFound == 0)
{
matchedSG = true;
System.out.println("Found the SD drive.");
drive = "sd"+driveLetters[d];
System.out.println(sasA);
hdsas.set(sasA , sas);
d = 0;
i++;
loadDrives(drive , sasA);
}
/* else if (sdFound != )
{
System.out.println("Error:" + sdFound);
System.out.println(d+ " "+ i);
}
*/
else if ( d >= 8)
{
System.out.println("Drive letter: " + driveLetters[d]);
System.out.println("Int: " + i);
// System.out.println(sdFound2);
System.out.println("sd error: "+ sdFound);
// System.out.println(stderr);
//System.out.println(sdFound2 + " m");
}
else
{
d++;
}
}
}
else
{
System.out.println("Folder: sg" + i + " could not be found.");
i++;
}
d =0;
}
}
Any help or suggestions would be awesome! Thanks.
EDIT:
The solution I found was to use the java library for testing if a directory exists rather than doing it through the linux command line.
Ex:
File location = new File("directory");
if (location.exists())
{
}
No idea why it works and doesn't crash, where as the linux command line did after a short period of time, but it does.
This is no direct answer to your question, but it still might help you:
I often have to find bugs in code like yours (very long methods with "global" variables, that is, variables declared at the beginning of a method and used all over then). Just by refactoring the code properly (short methods with a single purpose each), the cause of the bug becomes immediately visible to me and is fixed within a second (while the refactoring itself takes much longer).
I guess that's what everyone trying to offer you help is doing anyway: Refactor your code (probably only in one's head) so that is (much) more easy to understand what's going on.
The solution I found was to use the java library for testing if a directory exists rather than doing it through the linux command line.
Ex:
File location = new File("directory");
if (location.exists())
{
}
No idea why it works and doesn't crash, where as the linux command line did after a short period of time, but it does.