I want to get the content of a file inside a directory:
/sys/block/sda/device/model
I use this code to get the content:
String content = new String(Files.readAllBytes(Paths.get("/sys/block/sda/device/model")));
But in some scenarios, I have cases like this:
/sys/block/sda/device/model
/sys/block/sdb/device/model
/sys/block/sdc/device/model
How I can iterate all the directories starting with
sd* and print the file model?
Can you show me some example for Java 8 with filter?
Here is an example of how to do this using Java 8 features:
Function<Path,byte[]> uncheckedRead = p -> {
try { return Files.readAllBytes(p); }
catch(IOException ex) { throw new UncheckedIOException(ex); }
};
try(Stream<Path> s=Files.find(Paths.get("/sys/block"), 1,
(p,a)->p.getName(p.getNameCount()-1).toString().startsWith("sd"))) {
s.map(p->p.resolve("device/model")).map(uncheckedRead).map(String::new)
.forEach(System.out::println);
}
This is an example that strives for compactness and working stand-alone. For real applications, it’s likely that you would do it a bit differently. The task of using an IO operation as a Function which doesn’t allow checked exception is quite common so you might have a wrapper function like:
interface IOFunction<T,R> {
R apply(T in) throws IOException;
}
static <T,R> Function<T,R> wrap(IOFunction<T,R> f) {
return t-> { try { return f.apply(t); }
catch(IOException ex) { throw new UncheckedIOException(ex); }
};
}
Then you can use
try(Stream<Path> s=Files.find(Paths.get("/sys/block"), 1,
(p,a)->p.getName(p.getNameCount()-1).toString().startsWith("sd"))) {
s.map(p->p.resolve("device/model")).map(wrap(Files::readAllBytes))
.map(String::new).forEach(System.out::println);
}
But maybe you’d use newDirectoryStream instead even if the returned DirectoryStream is not a Stream and hence requires a manual Stream creation as this method allows passing a glob pattern like "sd*":
try(DirectoryStream<Path> ds
=Files.newDirectoryStream(Paths.get("/sys/block"), "sd*")) {
StreamSupport.stream(ds.spliterator(), false)
.map(p->p.resolve("device/model")).map(wrap(Files::readAllBytes))
.map(String::new).forEach(System.out::println);
}
Finally, the option to process the files as stream of lines should be mentioned:
try(DirectoryStream<Path> ds
=Files.newDirectoryStream(Paths.get("/sys/block"), "sd*")) {
StreamSupport.stream(ds.spliterator(), false)
.map(p->p.resolve("device/model")).flatMap(wrap(Files::lines))
.forEach(System.out::println);
}
Rather using st* it's better if you can first search the existing folder inside the path /sys/block by using below code.
Please find working example :-
String dirNames[] = new File("E://block").list();
for(String name : dirNames)
{
if (new File("E://block//" + name).isDirectory())
{
if(name.contains("sd")){
String content = new String(Files.readAllBytes(Paths.get("E://block//"+name+"//device//model")));
System.out.println(content);
}
}
}
Related
I have a (maybe simple) question. In my code I want to know whether there are one or more folder in a classpath or not. First things first: my code is working when using IDE, but not when it runs in a jar file. I understood that there is the way with - especially in Spring Boot - the class PathMatchingPatternResolver to get the resources. I have done this, but I can't get my code working under *.jar. The situation is as follows:
I want to look at a certain path if there are certain folder to get their names. If there are such folder, the names of them will be saved in a List. I need this List in further action. But how to get the folder from *.jar?
Here is what I have done so far:
public List<String> loadSupportedRecords(Meta metaFromTaxCase) {
List<String> vastRecordTypes = new ArrayList<>();
Map<String, String> values = new HashMap<>();
values.put(TAX_TYPE, metaFromTaxCase.getTaxonomie().getKey());
values.put(FISCAL_YEAR, metaFromTaxCase.getVeranlagungszeitraum());
values.put(TAXONOMIE_VERSION, metaFromTaxCase.getVersionDerTaxonomie());
var path = replaceVariablesInPathWithMapValues(vastConfigTemplatePath, values);
var indexOfRepo = path.lastIndexOf("{record-type}/");
var lengthOfVar = "{record-type}".length();
var subPath = path.substring(0, indexOfRepo + lengthOfVar);
try {
for (Resource resource : resourcePatternResolver.getResources(subPath)) {
vastRecordTypes.add(resource.getFilename()); // <-- This does not work
// I know that this does not work, but this is my newest commit.
// I tried with File Object and used the "listFiles()" method,
// but also failed.
}
return vastRecordTypes;
} catch (IOException e) {
throw new ResourceNotFoundException(
String.format(CLASSPATH_ERROR_MESSAGE, path, e.getMessage()));
}
}
Is there any way to get the folder names in IDE AND in *.jar running?
Thank you all for helping me as good as you can.
Finally I got things work. My code runs as follows:
public Set<String> loadSupportedRecords(Meta metaFromTaxCase) {
Set<String> vastRecordTypes = new HashSet<>();
Map<String, String> values = new HashMap<>();
values.put(TAX_TYPE, metaFromTaxCase.getTaxonomie().getKey());
values.put(FISCAL_YEAR, metaFromTaxCase.getVeranlagungszeitraum());
values.put(TAXONOMIE_VERSION,metaFromTaxCase.getVersionDerTaxonomie());
var path = replaceVariablesInPathWithMapValues(vastConfigTemplatePath, values);
try {
for (Resource resource : resourcePatternResolver.getResources(path)) {
vastRecordTypes.add(((ClassPathResource) resource).getPath().split("/")[8]);
}
return vastRecordTypes;
} catch (IOException e) {
throw new ResourceNotFoundException(
String.format(CLASSPATH_ERROR_MESSAGE, path, e.getMessage()));
}
}
As I learned, it is not possible to get "folder" in jar environment. It seems that all is treated as a file. So I searched the file-tree and used the above split method to get the individual folder name. In my code I can be sure, that the first 8 elements of the Array are always the same, so it can be hard coded. I also used a Set now instead of a List, to avoid double inserts (because there are a lot of files underneath the folder). Thanks to all.
I have been trying many of the examples provided and have yet to be successful. Here is the code I am currently trying, but getting an error in Eclipse on Paths.of (the of is underlined in red) that says: "rename in file".
String content;
try {
content = Files.readAllLines(Paths.of("C:", "Calcs.txt"));
} catch (IOException e1) {
e1.printStackTrace ();
}
System.out.println (content);
First it is not possible, if you get a list as return type, to assign this to a string. So you must write:
List<String> content;
Second regarding to the Java 8 documentation there is no method of available for this class. You can use the method get like this:
List<String> content = Files.readAllLines(Paths.get("C:", "Calcs.txt"));
Otherwise there exists a method of in the Path class since Java 11. Therefore you can write something like that:
List<String> content = Files.readAllLines(Path.of("C:", "Calcs.txt"));
You're probably looking for Paths.get:
String content;
try {
content = String.join("\n", Files.readAllLines(Paths.get("/home/hassan", "Foo.java")));
} catch (IOException e1) {
e1.printStackTrace ();
}
I am using Tess4j for using Tesseract-OCR technology and I have been using the following code:
During testing I wanted to test the catch close so I was feeding wrong information to Tesseract, which should result in TesseractException.
I managed to induce a TesseractException from the createDocuments() method.
Here is the stack trace:
Note that in the exception we can find doOcr()'s line 125, which is within the try-catch clause, but even though console shows a TesseractException being thrown, the code moves onto line 126 returning true.
I use net.sourceforge.tess4j.Tesseract to initiate the OCR proccess, but I tried net.sourceforge.tess4j.Tesseract1 too, which resulted the same red console output that is done by Tess4j, but no TesseractException.
My question is what am I doing wrong? I am just assuming there is an issue with my code, because TesseractExceptionis being thrown, but my code is not catching it.
Look at the source code of Tesseract.java:
#Override
public void createDocuments(String[] filenames, String[] outputbases, List<RenderedFormat> formats) throws TesseractException {
if (filenames.length != outputbases.length) {
throw new RuntimeException("The two arrays must match in length.");
}
init();
setTessVariables();
try {
for (int i = 0; i < filenames.length; i++) {
File workingTiffFile = null;
try {
String filename = filenames[i];
// if PDF, convert to multi-page TIFF
if (filename.toLowerCase().endsWith(".pdf")) {
workingTiffFile = PdfUtilities.convertPdf2Tiff(new File(filename));
filename = workingTiffFile.getPath();
}
TessResultRenderer renderer = createRenderers(outputbases[i], formats);
createDocuments(filename, renderer);
api.TessDeleteResultRenderer(renderer);
} catch (Exception e) {
// skip the problematic image file
logger.error(e.getMessage(), e);
} finally {
if (workingTiffFile != null && workingTiffFile.exists()) {
workingTiffFile.delete();
}
}
}
} finally {
dispose();
}
}
/**
* Creates documents.
*
* #param filename input file
* #param renderer renderer
* #throws TesseractException
*/
private void createDocuments(String filename, TessResultRenderer renderer) throws TesseractException {
api.TessBaseAPISetInputName(handle, filename); //for reading a UNLV zone file
int result = api.TessBaseAPIProcessPages(handle, filename, null, 0, renderer);
if (result == ITessAPI.FALSE) {
throw new TesseractException("Error during processing page.");
}
}
Exception is thrown at line 579. This method is called by a public method above - at line 551. This is inside the try-catch block with logger.error(e.getMessage(), e); in the catch body (line 555).
Now the question is what you really want to achieve?
If you don't want to see this log, you can configure slf4j to not print the log from this library.
If you want to get the actual exception, it is not possible as the library swallows it. I am not familiar with the library, but looking at the code it doesn't seem like there is any nice option - the method that throws the exception is private and is used only in this one place - under the try-catch block. However, the exception is thrown when api.TessBaseAPIProcessPages(...) returns ITessAPI.FALSE and api has a getter. So you could get it, call TessBaseAPIProcessPages(...) method and check for the result. This might be not ideal as you will probably be processing every image twice. Another solution is to fork the source code and modify it yourself. You might also want to contact the author and ask for advice - you could take it further and submit a pull request for them to approve and release.
Add pdf.ttf file to tessdata path (tessdata/pdf.ttf)
pdf.ttf
I'm encountering some problems by using the MatrixIO.loadcsv() function in ejml. In fact, I need to load a file into a matrix; i'm following this official example:
public static void main( String args[] ) {
DMatrixRMaj A = new DMatrixRMaj(2,3,true,new double[]{1,2,3,4,5,6});
try {
MatrixIO.saveCSV(A, "matrix_file.csv");
DMatrixRMaj B = MatrixIO.loadCSV("matrix_file.csv");
B.print();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
But when I try my code
DMatrixRMaj B = MatrixIO.loadCSV("sets.csv");
B.print();
I always obtain a FileNotFoundException... but the name of the file is correct and in the same folder of the source code. Where can be the problem?
The solution for me (I'm using Windows 10) is to use absolute path, because it seems not to recognize relative ones on my system, despite of the official examples.
How can I override removeEldestEntry method to saving eldest entry to file? Also how to limit the size of a file like I did it in LinkedHashMap. Here is code:
import java.util.*;
public class level1 {
private static final int max_cache = 50;
private Map cache = new LinkedHashMap(max_cache, .75F, true) {
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > max_cache;
}
};
public level1() {
for (int i = 1; i < 52; i++) {
String string = String.valueOf(i);
cache.put(string, string);
System.out.println("\rCache size = " + cache.size() +
"\tRecent value = " + i + " \tLast value = " +
cache.get(string) + "\tValues in cache=" +
cache.values());
}
I tried to use FileOutPutSTream :
private Map cache = new LinkedHashMap(max_cache, .75F, true) {
protected boolean removeEldestEntry(Map.Entry eldest) throws IOException {
boolean removed = super.removeEldestEntry(eldest);
if (removed) {
FileOutputStream fos = new FileOutputStream("t.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(eldest.getValue());
oos.close();
}
return removed;
}
But I have gained an error
Error(15,27): removeEldestEntry(java.util.Map.Entry) in cannot override removeEldestEntry(java.util.Map.Entry) in java.util.LinkedHashMap; overridden method does not throw java.io.IOException
Without IOExecptio compiler asks to handle IOexception and Filenotfoundexception.
Maybe another way exists? Pls show me example code, I am new in java and just trying to understand the basic principles of 2 level caching. Thx
You first need to make sure your method properly overrides the parent. You can make some small changes to the signature, such as only throwing a more specific checked exception that is a sub-class of a checked exception declared in the parent. In this case, the parent does not declare any checked exception so you can not refine that further and may not throw any checked exceptions. So you will have to handle the IOException locally. There are several ways you can do that, convert it to a RuntimeException of some kind and/or log it.
If you are concerned about the file size, you probably do not want to keep just the last removed entry but many of them - so you should open the file for append.
You need to return true from the method to actually remove the eldest and you need to decide if the element should be removed.
When working with files you should use try/finally to ensure that you close the resource even if there is an exception. This can get a little ugly - sometimes it's nice to have a utility method to do the close so you don't need the extra try/catch.
Generally you should also use some buffering for file I/O which greatly improves performance; in this case use wrap the file stream in a java.io.BufferedOutputStream and provide that to the ObjectOutputStream.
Here is something that may do what you want:
private static final int MAX_ENTRIES_ALLOWED = 100;
private static final long MAX_FILE_SIZE = 1L * 1024 * 1024; // 1 MB
protected boolean removeEldestEntry(Map.Entry eldest) {
if (size() <= MAX_ENTRIES_ALLOWED) {
return false;
}
File objFile = new File("t.tmp");
if (objFile.length() > MAX_FILE_SIZE) {
// Do something here to manage the file size, such as renaming the file
// You won't be able to easily remove an object from the file without a more
// advanced file structure since you are writing arbitrary sized serialized
// objects. You would need to do some kind of tagging of each entry or include
// a record length before each one. Then you would have to scan and rebuild
// a new file. You cannot easily just delete bytes earlier in the file without
// even more advanced structures (like having an index, fixed size records and
// free space lists, or even a database).
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(objFile, true); // Open for append
ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(fos));
oos.writeObject(eldest.getValue());
oos.close(); // Close the object stream to flush remaining generated data (if any).
return true;
} catch (IOException e) {
// Log error here or....
throw new RuntimeException(e.getMessage(), e); // Convert to RuntimeException
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e2) {
// Log failure - no need to throw though
}
}
}
}
You can't change the method signature when overriding a method. So you need to handle the exception in the overridden method instead of throwing it.
This contains a good explanation on how to use try and catch: http://download.oracle.com/javase/tutorial/essential/exceptions/try.html