How to mock file, java.nio.Path, Paths? - java

I have a method that has a few static classes as well as java.nio.Files,ResourceUtils, etc I am not sure how to write test cases for it as I keep getting NPE Paths.get(filePath);
Below is the method:
#Value("${file.path}")
private String filePath;
private List<MyJsonObj> readJSONFiles() throws IOException {
List<MyJsonObj> myJsonObjList = new ArrayList<>();
Gson gson = new GsonBuilder().setLongSerializationPolicy(LongSerializationPolicy.STRING).create();
Path folder = Paths.get(filePath);
try (DirectoryStream<Path> stream = Files.newDirectoryStream(folder)) {
for (Path entry : stream) {
String file = folder + "\\" + entry.getFileName().toString();
MyJsonObj jsonObj = gson.fromJson(new FileReader(ResourceUtils.getFile(file)), MyJsonObj.class);
myJsonObjList.add(jsonObj);
}
return myJsonObjList;
}catch (IOException e) {
logger.error(Arrays.asList(e.getStackTrace()).toString());
}
}

Related

A question about the Java File class and its Serialization maybe?

I don't know why the isFile() of the element f in the files list traversed by the for loop in the FileInit class in the code below is always false.false. But if delete the content related to FileItem, it will return to normal.It's kind of weird to me, and I didn't find a targeted answer. It might be some peculiarity of Java.A cloud disk project is used to learn Java, using Google's Gson library.
public class FileInit {
String path;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
//Query file method, will return a list containing file information
public String queryFiles() throws NoSuchAlgorithmException, IOException {
//Query the path and build a File collection
File file = new File(path);
File[] files = file.listFiles();
//Build a List to store the converted FileItem
List<FileItem> fileItems = new ArrayList<>();
//Traversing files to make judgments
for (File f:files){
FileItem fileItem = new FileItem(f);
fileItem.printFile();
fileItems.add(fileItem);
}
Gson gson = new Gson();
return gson.toJson(fileItems);
}
//formatted output
public void printFiles(String files){
Gson gson = new Gson();
Type type = new TypeToken<List<FileItem>>(){}.getType();
List<FileItem> fileItems = gson.fromJson(files, type);
// Format output file list
int count = 0;
for (FileItem f :fileItems ) {
String name;
if (f.getFileType()==null){
name = f.getFileName() + "/";
}else {
name = f.getFileName();
}
System.out.printf("%-40s", name);
count++;
if (count % 3 == 0) {
System.out.println();
}
}
System.out.println();
}
//Change directory command
public void changeDic(String addPath){
File fileDic1 = new File(path+addPath);
File fileDic2 = new File(addPath);
if (addPath.equals("..")) {
File parent = new File(path).getParentFile();
if (parent != null) {
this.path = parent.getPath();
}else{
System.out.println("Parent directory does not exist");
}
}
else {
if (fileDic1.exists()){
this.path = path+addPath;
} else if (fileDic2.exists()) {
this.path = addPath;
}else{
System.out.println("Illegal input path");
}
}
}
}
public class FileItem {
private String fileName;
private String fileHash;
private String filePath;
private long fileLength;
private String fileType;
//Construction method of FileItem
/*
Build a construction method that only needs fileName and filePath, and judge whether to calculate the hash value, file size, and file type according to the folder or file
*/
public FileItem(String fileName,String filePath) {
this.fileName = fileName;
this.filePath = filePath;
File file =new File(this.filePath+"/"+this.fileName);
if (file.isFile()){
try {
//Get the file size through the file built-in method
this.fileLength = file.length();
// Define a regular expression for extracting the suffix of the file name
String regex = "\\.(\\w+)$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(fileName);
// If the match is successful
if (matcher.find()) {
// Get the suffix of the file name
this.fileType = matcher.group(1);
}else{
this.fileType = null;
}
//Calculate the Hash value of the file by calling the FileHash method
this.fileHash=FileHash(file.getPath());
System.out.printf(fileHash);
System.out.print("\n");
} catch (NoSuchAlgorithmException | IOException e) {
throw new RuntimeException(e);
}
}else{
this.fileName=fileName;
this.fileLength=0;
this.fileType = null;
this.fileHash=null;
}
}
//Build a constructor that only needs a json file
public FileItem(String json){
Gson gson = new Gson();
FileItem fileItem = gson.fromJson(json,FileItem.class);
this.fileName=fileItem.getFileName();
this.filePath=fileItem.getFilePath();
this.fileHash=fileItem.getFileHash();
this.fileLength=fileItem.getFileLength();
this.fileType=fileItem.getFileType();
}
//Realize mutual conversion between FileItem and File class
public File toFile(){
return new File(this.filePath+"/"+this.fileName);
}
public FileItem(File file) throws NoSuchAlgorithmException, IOException {
FileItem fileItem = new FileItem(file.getName(),file.getPath());
this.fileName=fileItem.getFileName();
this.filePath=fileItem.getFilePath();
this.fileHash=fileItem.getFileHash();
this.fileLength=fileItem.getFileLength();
this.fileType=fileItem.getFileType();
}
//Display FileItem related information
public void printFile(){
if (fileType==null){
System.out.println(fileName+"是文件夹");
}else {
System.out.println(fileName+"是"+fileType+"文件");
}
double fileLenOp=(double)fileLength;
//Different file sizes use different output methods
if(fileLength<=1024*1024){
System.out.printf("file size is:%.3fKB\n",fileLenOp/1024);
} else if ((fileLength<1024*1024*1024)) {
System.out.printf("file size is:%.3fMB\n",fileLenOp/1024/1024);
}else {
System.out.printf("file size is:%.3fGB\n",fileLenOp/1024/1024/1024);
}
System.out.println("file hash is:"+fileHash);
}
//Getter and Setter methods for FileItem
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileHash() {
return fileHash;
}
public void setFileHash(String fileHash) {
this.fileHash = fileHash;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public long getFileLength() {
return fileLength;
}
public void setFileLength(long fileLength) {
this.fileLength = fileLength;
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
}
I try to query the file information in a folder by using the methods related to the File class. And return them as a collection. Then realize the conversion of the File class and the FileItem class by traversing this collection to form a new FileItem class collection , so that it can be converted into Json format data for network transmission. However, all fileitems in the generated FileItem collection are judged as folders. And if you comment out the FileItem related content, the judgment of File will be normal, but if you don’t do this , the judgment of File will always remain false.

Buffered Writer not writing to txt file from ArrayList

I am having a spot of bother getting BufferedWriter to write output to a txt file I have.
When I compile the program, I do not get any errors but the txt file arrives in my project blank.
I have looked on here at similar questions and tried a few of the proposed solutions to resolve it without success, like closing the stream etc
public void storeToDoItemsOntoTxtFile () throws IOException {
Path path = Paths.get(fileName);
BufferedWriter buffyWriter = Files.newBufferedWriter(path);
try {
Iterator<ToDoItem> bigIterator = toDoItems.iterator();
while (bigIterator.hasNext()) {
ToDoItem item = bigIterator.next();
buffyWriter.write(String.format("%s\t%S\t%s", item.getShortDescription(), item.getDetails(), item.getDeadline().format(formatter)));
buffyWriter.newLine();
}
} finally {
if (buffyWriter !=null) {
buffyWriter.close();// when we are done working with the writer
}
}
}
BufferedReader
public void loadToDoItemsFromTxtFile() throws IOException {
toDoItems = FXCollections.observableArrayList();
Path path = Paths.get(fileName);
BufferedReader buffyReader = Files.newBufferedReader(path);
String buffyInput;
try {
while ((buffyInput = buffyReader.readLine()) !=null) {
String [] itemPieces = buffyInput.split("\t");
String shortDescription = itemPieces[0];
String details = itemPieces[1]; //
String dateString = itemPieces [2];
LocalDate date = LocalDate.parse(dateString, formatter);
ToDoItem toDoItem = new ToDoItem(shortDescription,details,date);
toDoItems.add(toDoItem);
}
} finally {
if (buffyReader != null) {// ie the buffy reader states that there is a toDoItem" in the txt file
buffyReader.close();
}
}
}

Programmatically creating jar file

I am running Mac OSX Mavericks. Right now I am creating a JAR file from a folder (org, the package). When I use this code from here:
public void run() throws IOException
{
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
JarOutputStream target = new JarOutputStream(new FileOutputStream("/Users/username/Library/Application Support/VSE/temp/output.jar"), manifest);
add(new File("/Users/username/Library/Application Support/VSE/temp/org"), target);
target.close();
}
private void add(File source, JarOutputStream target) throws IOException
{
BufferedInputStream in = null;
try
{
if (source.isDirectory())
{
String name = source.getPath().replace("\\", "/");
if (!name.isEmpty())
{
if (!name.endsWith("/"))
name += "/";
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
target.closeEntry();
}
for (File nestedFile: source.listFiles())
add(nestedFile, target);
return;
}
JarEntry entry = new JarEntry(source.getPath().replace("\\", "/"));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true)
{
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
}
finally
{
if (in != null)
in.close();
}
}
When I extract the JAR file, There is a META-INF folder, but instead of having the org folder in the extracted jar, I have my Users folder copied into it (except because of it's size, its wasn't filled with all my stuff and my application crashed). I'm expecting this is because the code was written for a Windows system, and the differences with the filesystem (such as \ or /). How would I make the code include only the "org" directory, and not everything leading up to it?
Provided you use Java 7+ you may easily do this by using one of my packages in combination with the zip filesystem provider of the JDK to create it:
private static final Map<String, ?> ENV = Collections.singletonMap("create", "true");
public void run()
throws IOException
{
final Path zipPath = Paths.get("/Users/username/Library/Application Support/VSE/temp/output.jar");
final Path srcdir = Paths.get("/Users/username/Library/Application Support/VSE/temp/org");
final URI uri = URI.create("jar:" + zipPath.toUri());
Files.deleteIfExists(zipPath);
try (
final FileSystem zipfs = FileSystems.newFileSystem(uri, ENV);
) {
copyManifest(zipfs);
copyDirectory(srcdir, zipfs);
}
}
private void copyManifest(final FileSystem zipfs)
throws IOException
{
final Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
Files.createDirectory(zipfs.getPath("META-INF/");
try (
final OutputStream out = Files.newOutputStream(zipfs.getPath("META-INF/MANIFEST.MF"));
) {
manifest.write(out);
}
}
private void copyDirectory(final Path srcdir, final FileSystem zipfs)
{
final String lastName = srcdir.getFileName().toString();
final Path dstDir = zipfs.getPath(lastName);
Files.createDirectory(dstDir);
MoreFiles.copyRecursive(srcDir, dstDir, RecursionMode.FAIL_FAST);
}

How to return multple files from ZipInputStream

I'm downloading a zip file from an ftp server. The zip file contains a couple csv files. I'm trying to extract both csv files so that I can pass them into Opencsv, but I seem to be having some issues. I'm assuming there must be a better way to handle this than the way I'm doing it below. How do you return my csv files so that they are available in a list for my csv reader?
My code
ftp.retrieveFile(file, output);
InputStream inputStream = new ByteArrayInputStream(output.toByteArray());
Map<String, InputStream> inputStreams = new HashMap<>();
if (importTask.isZipfile()) {
inputStreams.put("products", importUtils.getZipData(new ZipInputStream(inputStream), importTask.getFilename()));
if(importTask.getCustomerFilename() != null) {
inputStream = new ByteArrayInputStream(output.toByteArray());
inputStreams.put("customers", importUtils.getZipData(new ZipInputStream(inputStream), importTask.getCustomerFilename()));
}
} else {
inputStreams.put("products", inputStream);
}
ftp.logout();
ftp.disconnect();
return inputStreams;
Zip
public InputStream getZipData(ZipInputStream zip, String filename) throws FileNotFoundException, IOException {
for (ZipEntry e; (e = zip.getNextEntry()) != null;) {
if (e.getName().equals(filename)) {
return zip;
}
}
throw new FileNotFoundException("zip://" + filename);
}
If you use Java 7+ you have an easier solution than that; you can just use the zip filesystem provider.
Here is some sample code; note that you need to .close() the generated InputStreams and FileSystems:
public static void getFsFromZipFile(final Path zipFile)
throws IOException
{
final URI uri = URI.create("jar:" + zipFile.toUri());
final Map<String, ?> env = Collections.singletonMap("readonly", "true");
return FileSystems.newFileSystem(uri, env);
}
public static getInputStreamFromZip(final FileSystem zipfs, final String name)
throws IOException
{
return Files.newInputStream(zipfs.getPath(name));
}
This is not how I'd recommend you do it however. What I'd recommend is this:
final Map<String, Path> getFilesFromZip(final Path zipFile, final String... names)
throws IOException
{
Path tmpfile;
final URI uri = URI.create("jar:" + zipFile.toUri());
final Map<String, ?> env = Collections.singletonMap("readonly", "true);
final Map<String, Path> ret = new HashMap<>();
try (
final FileSystem zipfs = FileSystems.newFileSystem(uri, env);
) {
for (final String name: names) {
tmpfile = Files.createTempFile("tmp", ".csv");
Files.copy(zipfs.getPath(name), tmpfile);
ret.put(name, tmpfile);
}
return ret;
}
}

display path of all files in the folder relative to the first file encountered in that folder

I am new to Java, I tried to practice some example but I am facing issue in the file handling topic.
Following is the example that what I am trying.
T1--> T2--> T3--> T4--> Gan--> q.txt
|
--> Lin-->Img-->s.png
|
--> p.txt
This is the folder structure.
And I want output in the following format.
p.txt
Lin/Img/s.png
Gen/q.txt
That means when the first file is getting in any directory, after that next file will be printed with the path from first file is got.
The above directory structure is not fixed. It may change.
Now following are code that I have did but I am not getting proper output:
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
class FileProgram {
private ArrayList<File> listOfDirectories = new ArrayList<File>();
private ArrayList<File> rawFiles = new ArrayList<File>();
private ArrayList<String> parentDir = new ArrayList<String>();
private ArrayList<String> filesToDisplay = new ArrayList<String>();
private Iterator i, listDir;
private boolean firstFile = false;
private String parents = "";
public void getDetails(File file) {
try {
if (file.exists()) {
File directoies[] = file.listFiles();
if (!rawFiles.isEmpty()) {
rawFiles.clear();
}
for (File f : directoies) {
rawFiles.add(f);
}
i = rawFiles.iterator();
while (i.hasNext()) {
File isFile = (File) i.next();
if (isFile.isFile()) {
displayFiles(isFile);
}
if (isFile.isDirectory()) {
listOfDirectories.add(isFile);
}
}
iterateInnerDirectories();
} else {
System.out.println("Invalid File Path");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
FileProgram ray = new FileProgram();
ray.getDetails(new File("D:\\Temp"));
}
private void iterateInnerDirectories() {
listDir = listOfDirectories.iterator();
while (listDir.hasNext()) {
File isFile = (File) listDir.next();
File f = isFile;
listOfDirectories.remove(isFile);
getDetails(isFile);
}
}
private void displayFiles(File file) {
if (firstFile == false) {
firstFile = true;
String rootPath = file.getParent();
rootPath = rootPath.replace(file.getName(), "");
parentDir.add(rootPath);
parents = file.getParentFile().getName();
System.out.println(file.getName());
filesToDisplay.add(file.getName());
} else {
String rootPath = file.getParent();
rootPath = rootPath.replace(file.getName(), "");
if (parentDir.contains(rootPath)) {
parents = file.getParentFile().getName();
System.out.println(file.getName());
filesToDisplay.add(file.getName());
} else {
System.out.println(file);
}
}
}
}
Please anybody can help me to get proper output that I have mentioned above.
Thanks in advance.
Unless you're using a Java prior to Java 7 I would strongly suggest to use Path.
You can walk a directory recursively using Files.walkFileTree().
Once you encounter a file (!Files.isDirectory()), you can get its parent with Path.getParent(). And you can print the relative path to this parent of all further file using Path.relativize().
Short, Simple Implementation
In this implementation I don't even use Files.isDirectory() because visitFile() is only called for files:
public static void printFiles(Path start) {
try {
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
Path parent;
#Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
if (parent == null)
parent = file.getParent();
System.out.println(parent.relativize(file));
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
And this is how you call it:
printFiles(Paths.get("/path/to/T1"));

Categories