"non-static variable cannot be referenced from a static context" and I only have 1 class - static

public class FileReaderProgram
{
String stringComponent;
int integerComponent;
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.println("Enter the absolute path of the file");
String fileName = in.next(); //Gets the file from the user
File inFile = new File(fileName);
Scanner fileReader = new Scanner(inFile); //Constructs Scanner for reading the file
while (fileReader.hasNextLine())
{
String line = fileReader.nextLine(); //Gets line from the file
Scanner lineScanner = new Scanner(line); //Constructs new scanner to analize the line
String stringComponent = lineScanner.next(); //Obtains the first word of the data line
while (!lineScanner.hasNextInt()) // Checks if there is another word in the string portion of the line
{
stringComponent = stringComponent + " " + lineScanner.next();
}
int integerComponent = lineScanner.nextInt(); //Obtains the integer part of the data line
lineScanner.nextLine(); //Consume the newline
}
System.out.println(stringComponent);
System.out.println("integerComponent);
}
}
My simple little code that's supposed to read multiple lines of a file (each line containing a string and an integer separated by a comma) and then read them back to me so I know its working. But I get the error message in the title for both variables and it highlights where I have them in System.out. Im utterly confused why, help please?

Because main method is static, it cannot access any of the non-static variables defined in FileReaderProgram. These variables are class-member variables and require an instance of FileReaderProgram to hold them. You would need to either change them to static:
static String stringComponent;
int integerComponent;
or create a FileReaderProgram instance and access them through that.
public static void main(String[] args)
{
FileReaderProgram frp = new FileReaderProgram();
.
.
.
}
Since you are redefining variables with the same names in the while loop, these are hiding the ones defined in the class, but the following 2 lines:
System.out.println(stringComponent);
System.out.println(integerComponent);
since they are outside the loop, are trying to access the member variables, which is invalid, like I said above.

Is this your completed code? You need to import scanner for one thing. You need to import io as well. Also, the last line, you didn't close off the string.
You will also need a try catch unless you throw the FileNotFoundException.
The issue here is that you do have a class, however, you only have a static method, which is main. Since main is static, you can't instantiate variables outside of main the way you did. You did it as if you have an object.
Two solutions: Move those two declarations into main and your good to go. Other solution is to add the keyword static before each variable. I would suggest you move stringComponent and intComponent inside main to prevent unwanted access. Limit their scope. The reason why it freaks out on the stringComponent is because that's an object. And if I remember correctly, there are no static references in the String API.

Related

How can I password protect a file regardless of its extension in Java 8 ro Java 10

I have tried doing this by encrypting individual files but I have a lot of data (~20GB) and hence it would take a lot of time. In my test it took 2.28 minutes to encrypt a single file of size 80MB.
Is there a quicker way to be able to password protect that would apply to any any file (text/binary/multimedia)?
If you are just trying to hide the file from others, you can try to encrypt the file path instead of encrypting the whole huge file.
For the path you mentioned: text/binary/multimedia, you can try to encrypt it by a method as:
private static String getEncryptedPath(String filePath) {
String[] tokens = filePath.split("/");
List<String> tList = new ArrayList<>();
for (int i = 0; i < tokens.length; i++) {
tList.add(Hashing.md5().newHasher() // com.google.common.hash.Hashing;
.putString(tokens[i] + filePath, StandardCharsets.UTF_8).hash().toString()
.substring(2 * i, 2 * i + 5)); // to make it impossible to encrypt, add your custom secret here;
}
return String.join("/", tList);
}
and then it becomes an encrypted path as:
72b12/9cbb3/4a5f3
Once you know the real path text/binary/multimedia, any time you want to access the file, you can just use this method to get the real file path 72b12/9cbb3/4a5f3.

Splitting a text file where the information are separated in different lines

So, I have a text file where the information are separated by the enter key (I don't know how to explain, I will paste the code and some stuff).
cha-cha
Fruzsina
Ede
salsa
Szilvia
Imre
Here's how the text file looks like, and I need to split it into three parts, the first being the type of the dance, and then dancer 1 and dancer 2.
using System;
using System.Collections.Generic;
using System.IO;
namespace tanciskola
{
struct tanc
{
public string tancnev;
public string tancos1;
public string tancos2;
}
class Program
{
static void Main(string[] args)
{
#region 1.feladat
StreamReader sr = new StreamReader("tancrend.txt");
tanc[] tanc = new tanc[140];
string[] elv;
int i = 0;
while (sr.Peek() != 0)
{
elv = sr.ReadLine().Split('I don't know what goes here');
tanc[i].tancnev = elv[0];
tanc[i].tancos1 = elv[1];
tanc[i].tancos2 = elv[2];
i++;
}
#endregion
Console.ReadKey();
}
}
}
Here is how I tried to solve it, although I don't really get how I should do it. The task is would be to display the first dance and the last dance, but for that I need to split it somehow.
As mentioned in my comments, you seem to have a text file where each item is on a new line, and a set of 3 lines constitutes a single 'record'. In that case, you can simply read all the lines of the file, and then create your records, like so:
var v = File.ReadLines("file path");
tancr[] tanc = new tancr[140];
for (int i = 0; i < v.Count(); i += 3)
{
tanc[i/3].tancnev= v.ElementAt(i);
tanc[i/3].tancos1 = v.ElementAt(i + 1);
tanc[i/3].tancos2 = v.ElementAt(i + 2);
}
Note: ReadLines() is better when the file size is large. If your file is small, you could use ReadAllLines() instead.
To split by the "enter character" you can use Environment.NewLine in .NET:
https://msdn.microsoft.com/en-us/library/system.environment.newline(v=vs.110).aspx
elv = sr.ReadAllText().Split(new string[] {Environment.NewLine}, StringSplitOptions.None);
This constant will contain the sequence that is specific to your OS (I'm guessing Windows).
You should be aware that the characters used for newlines is different for Windows vs. Linux/Unix. So in the rare event that someone edits your file on a different OS, you can run into problems.
On Windows, newline is a two character sequence: carriage-return + line-feed (ASCII 13 + 10). On Linux it is just line-feed. So if you wanted to be extra clever, you could first check for CRLF and if you only get one element back from Split() then try just LF.

Is there a way to make the output file of a stream:file?fileName= dynamic?

Given a simple route like this
route.from("direct:foo")
.split()
.tokenize("\n")
.streaming()
.to("stream:file?fileName=target/streaming${header.count}.txt&closeOnDone=true");
which I then trigger with this
#Test
public void splitAndStreamToFile() {
StringBuilder builder = new StringBuilder();
for(int i = 0; i < 500; i++) {
builder.append(i);
builder.append("\n");
}
for(int i = 0; i < 10; i++) {
template.sendBodyAndHeader(builder.toString(), "count", i);
}
}
I get one big file that contains 10 times 500 lines, where I would have hoped to have 10 files that contain 500 lines each.
In other words, it seems that the fileName in the stream:file endpoint is not dynamic. I am wondering if this is at all possible? My google-fu turned up nothing so far.
EDIT:
With Claus' answer, I got it to work like this:
route.from("direct:foo")
.split()
.tokenize("\n")
.streaming()
.recipientList(route.simple("stream:file?fileName=target/streaming${header.count}.txt&closeOnDone=true"));
Its a dynamic to which there is an EIP pattern for:
http://camel.apache.org/how-to-use-a-dynamic-uri-in-to.html
But it could be a good idea to support the file/simple language on the fileName option as the regular file component does. Fell free to log a JIRA ticket about this improvement.
Sourcecode of the StreamProducer looks like it does not support any of the expression languages of Camel yet:
private OutputStream resolveStreamFromFile() throws IOException {
String fileName = endpoint.getFileName();
ObjectHelper.notEmpty(fileName, "fileName");
LOG.debug("About to write to file: {}", fileName);
File f = new File(fileName);
// will create a new file if missing or append to existing
f.getParentFile().mkdirs();
f.createNewFile();
return new FileOutputStream(f, true);
}
See sourecode.
If you need dynamic filenames, you should take a look at the file component, which supports the file language and the CamelFileName header.
In short,
toD uri=stream:file...
will do it.
The "toD" basically translates the "simple" or "file language" before it hits the stream component code...so that works for "fileName=..."

Add Elements to nullable Vector

Alright, so I got a private ?Vector $lines which is empty when constructing the object and now I want to add strings to that Vector. The following Hack code works well:
<?hh
class LineList {
private ?Vector<string> $lines;
public function addLine(string $line): void {
$this->file[] = trim($line);
}
}
But when checking the code with hh_client, it gives me the following warning:
$this->file[]]: a nullable type does not allow array append (Typing[4006])
[private ?Vector<string> $lines]: You might want to check this out
Question: How do I add elements to the Vector without that the checker pushs this warning?
The easiest way would be to not use a nullable Vector. private Vector<string> $lines = Vector {}; gets around the need for a constructor too.
Otherwise, you'll need to check if the value isn't null, then append to it:
public function addLine(string $line): void {
$vec = $this->lines;
if ($vec !== null) $vec[] = trim($line);
}
You can't just check if $this->lines !== null as it is possible for it to change value between checking and appending (with something like a tick function), hence why it is assigned to a local variable instead.

removing elements of arrqy error

I have a csv file which contains the numbers of buttons. I want to make a function that reads these numbers and set the number of a class that I have made and called FButton.
First I have declared an array of FButtons in my header file.
FButton buttons[10];
Now in the cpp file I have written the following code to set the numbers of the buttons:
QFile f("Buttons.csv");
if (f.open(QIODevice::ReadOnly))
{
int i=0;
QString data;
data = f.readAll();
QStringList vals = data.split(';');
while (!vals.isEmpty())
{
buttons[i].setNumber(vals[0].toInt());
vals.removeAt(0);
i++;
}
f.close();
}
The function setNumber is given by:
void FButton::setNumber(int butNumber)
{
number=butNumber;
}
It is possible for me to build the code, but when i try to run it an error occurs:
GUI.exe is no longer working.
Can somebody tell me what is wrong with my code?
Wouldn't you have more values in your CSV than the size of buttons array (or whatever collection it is) ? Or having uninitialized objects in buttons ?

Resources