DELETE_ON_CLOSE deletes files before close on Linux - java

I have this following code using Java 7 nio API:
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class TestDeleteOnClose {
public static void main(String[] args) throws IOException {
Path tmp = Files.createTempFile("a", "b");
OutputStream out = Files.newOutputStream(tmp, StandardOpenOption.DELETE_ON_CLOSE);
ObjectOutputStream os = new ObjectOutputStream(out);
os.write(0);
os.flush();
System.out.println(Files.exists(tmp));
os.close();
System.out.println(Files.exists(tmp));
}
}
On Windows, I see what I expect, i.e true false. On Linux I see false false. Is it expected? Am I doing something wrong?
The fact that the file is deleted too early is problematic since I need to test it for its size for instance after having written to it.
I use jdk7u25 on both Linux and Windows and could reproduce on machines with RedHat or ArchLinux on it.
EDIT: even if I test for file existence before another call to os.write() I am told the file does not exist anymore. If I open the file with the CREATE options, then I will see true true.

It looks like the Linux JVM deletes the file as soon as you open it, which makes sense as you can do that on Linux. That's how I would implement it too. You'll have to keep track of how much has been written to the file yourself, e.g. by interposing a FilterOutputStream that counts bytes.

Related

How do I reference the image file in my program appropriately without it causing an error?

Here's my code
The working directory for my program is printed at the bottom along with the error message, and on the left hand side of the screen my download png is located directly within my test project where the working directory is supposed to be. I have also tried using the direct file path of my download png within the getResource() method, but that didn't work either (I used double backslashes so that wasn't the issue).
package test;
import javax.swing.ImageIcon;
import javax.swing.Icon;
import java.io.File;
public class Test{
public Test() {
System.out.println(new File(".").getAbsolutePath());
ImageIcon download = new ImageIcon(getClass().getResource("download.png"));
}
public static void main(String[] args) {
new Test();
}
}
(Yes I know I didn't have to import Icon but I wanted to match what I had in the picture)
All I had to do was put the download.pgn file in the package where my class was located rather than the project that the absolute path was telling me to put it and the code worked. Hopefully this helps others who are having the same problem

How can I fix the project build path error? I can't import the java.lang.math for a Java 8/9 Calculator app

I am developing a simple calculator application in Java 8/9 in Eclipse. I am working on the power operation (as in "to the power of" used in math). I want to use the Math.power() instead of a for loop. However, I am having trouble importing the java math package into the program. The internet says to add import java.lang.math. When I try to code it in, I receive a notice of "Cannot Perform Operation. This compilation unit is not on the build path of the Java Project". What am I overlooking and/or doing wrong? Please provide suggestions or feedback.
Please note: Yes this is an academic assignment. To make this clear, I am not asking for the coding of the power operation. This issue is specifically about the importing the math package.
power operation (power.java)
package org.eclipse.example.calc.internal.operations;
import org.eclipse.example.calc.BinaryOperation;
// import java.lang.math; produces error
// Binary Power operation
public class Power extends AbstractOperation implements BinaryOperation {
// code removed. not relevant to SOF question.
}
Main (calculator.java)
package org.eclipse.example.calc.internal;
import org.eclipse.example.calc.BinaryOperation;
import org.eclipse.example.calc.Operation;
import org.eclipse.example.calc.Operations;
import org.eclipse.example.calc.UnaryOperation;
import org.eclipse.example.calc.internal.operations.Power;
import org.eclipse.example.calc.internal.operations.Equals;
import org.eclipse.example.calc.internal.operations.Minus;
import org.eclipse.example.calc.internal.operations.Plus;
import org.eclipse.example.calc.internal.operations.Divide;
import org.eclipse.example.calc.internal.operations.Square;
public class Calculator {
private TextProvider textProvider;
private String cmd;
private boolean clearText;
private float value;
public static String NAME = "Simple Calculator";
public Calculator(TextProvider textProvider) {
this.textProvider = textProvider;
setupDefaultOperations();
}
private void setupDefaultOperations() {
new Power();
new Equals();
new Minus();
new Plus();
new Divide();
new Square();
}
....
BTW, I use camel Case normally, but the academic project name everything including file names in standard writing format.
EDIT: After reading a response, I realized I forget to mention this. I can't get any further than typing import java., then the error pop-ups. Then I can't type the rest of the import statement
Image of package hierarchy
Your project is not configured correctly. You have no source dir at all. The src dir should be marked as source dir; right click it and tell eclipse about this, or, as it is a maven project, it's more likely a broken pom. Also, why are you using the org.eclipse package? If you work for SAP, it should be com.sap.

Any standard technique to handle file modification using separate application? [duplicate]

I'm writing here mostly for advice on where to start. I've already implemented a class that will recursively watch a directory using Java's WatchService. It works quite alright for detecting changes, but I've noticed a fatal flaw: I cannot delete directories that are being watched that contain directories that are being watched. This seems to be a limitation of WatchService.
I have also looked into Apache's VFS FileListener a bit, but before I spend another 6-or-so hours of my time building some kind of wrapper around it, I figured maybe I'd just ask those more knowledgeable than myself.
I need the directories being watched to be fully manipulable, with the exception that the root directory being watched will not be deleted or renamed. Does there already exist a good class I can work with to monitor files and directories that does not lock files or folders? I'm trying to avoid a polling/hash comparison approach, but I feel more and more as if I will need to use that approach and burn through a ton of CPU resources. Where do I start with this? Ideally, I need to:
-Detect creation of files and directories
-Detect deletion of files and directories
-Detect renaming of files and directories
-Detect modification of files
-Detect movement of files between directories
I've also seen some suggest that watchers are unreliable and that they use a combination of the two (polling occasionally in case the watcher failed somewhere), but man that sounds like a real pain that I'd rather avoid if it isn't the best way anyways. I have a feeling I'll need polling and hashing, especially since I want to detect moving and renaming of files, but please do tell if better options exist.
Thanks in advance, and sorry for the not-so-code-specific question!
This will allow you to experiment with creating, deleting, moving and renaming files under D:\Temp, and should allow you to learn what you need:
import static com.sun.nio.file.ExtendedWatchEventModifier.FILE_TREE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
public class Foo3
{
public static void main(String[] args) throws Exception
{
FileSystem fs = FileSystems.getDefault();
WatchService ws = fs.newWatchService();
Path pTemp = Paths.get("D:/Temp");
pTemp.register(ws, new WatchEvent.Kind[] {ENTRY_MODIFY, ENTRY_CREATE, ENTRY_DELETE}, FILE_TREE);
while(true)
{
WatchKey k = ws.take();
for (WatchEvent<?> e : k.pollEvents())
{
Object c = e.context();
System.out.printf("%s %d %s\n", e.kind(), e.count(), c);
}
k.reset();
}
}
}

How to access the remote .mdb file in shared folder using java and jackcess from linux machine

This is my first post. I am trying to open the remote .mdb file which is in shared folder in Windows machine from the linux machine using jackcess lib. and set the table values in busineess object. I wrote the below code.
Scenario 1 : I have run the code from windows machine it is working fine. Scenario 2 : If i run the code from linux machine it is getting file not found exception. Hope it should be small mistake. Please correct me what am missing here .
package com.gg.main;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Table;
import com.penske.model.Login;
public class Test {
public static void main(String args[]){
Table table = null;
Database db = null;
Login login = null;
ArrayList<Login> rowList = null;
try {
rowList = new ArrayList();
db = Database.open(new File("//aa.bb.com/file/access.mdb"));
table = db.getTable("Maintenance");
System.out.println(Database.open(new File("//aa.bb.com/file/access.mdb"))
.getTable("Maintenance").getColumns());
for(Map<String, Object> row : table) {
login = new Login();
if(row.get("Req_ID")!=null){
login.setId(row.get("Req_ID").toString());
}
if(row.get("Name")!=null){
login.setName(row.get("Name").toString());
}if(row.get("Loc")!=null){
login.setLoc(row.get("Loc").toString());
}
rowList.add(login);
}
login.setRowList(rowList);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
Linux does not have native support for Windows' UNC path, as you use them here:
new File("//aa.bb.com/file/access.mdb")
You'll have to mount the remote filesystem somewhere in your Linux filesystem where your program can access it and then replace the paths in your program to use that local filesystem path, using smbfs or something like it. It's been a long time since I've had to interact with Windows machines, but it should go something like this:
mount -t smbfs -o username=foo,password=bar //aa.bb.com/file /mnt/whatever_you_choose_to_name_it
See the manpage for smbmount for details.
Of course, if your program is supposed to start automatically eg. as part of the system booting, you'll have to see to it that the filesystem is automatically mounted as well. See fstab(5).

Java: CaptureDeviceManager#getDeviceList() is empty?

I am trying to print out all of the capture devices that are supported using the #getDeviceList() method in the CaptureDeviceManager class and the returned Vector has a size of 0.
Why is that? I have a webcam that works - so there should be at least one. I am running Mac OS X Lion - using JMF 2.1.1e.
Thanks!
CaptureDeviceManager.getDeviceList(Format format) does not detect devices. Instead it reads from the JMF registry which is the jmf.properties file. It searches for the jmf.properties file in the classpath.
If your JMF install has succeeded, then the classpath would have been configured to include all the relevant JMF jars and directories. The JMF install comes with a jmf.properties file included in the 'lib' folder under the JMF installation directory. This means the jmf.properties would be located by JMStudio and you would usually see the JMStudio application executing correctly. (If your JMF install is under 'C:\Program Files', then run as administrator to get around UAC)
When you create your own application to detect the devices, the problem you described above might occur. I have seen a few questions related to the same problem. This is because your application's classpath might be different and might not include the environment classpath. Check out your IDE's properties here. The problem is that CaptureDeviceManager cannot find the jmf.properties file because it is not there.
As you have found out correctly, you can copy the jmf.properties file from the JMF installation folder. It would contain the correct device list since JMF detects it during the install (Check it out just to make sure anyway).
If you want do device detection yourself, then create an empty jmf.properties file and put it somewhere in your classpath (it might throw a java.io.EOFException initially during execution but that's properly handled by the JMF classes). Then use the following code for detecting webcams...
import javax.media.*;
import java.util.*;
public static void main(String[] args) {
VFWAuto vfwObj = new VFWAuto();
Vector devices = CaptureDeviceManager.getDeviceList(null);
Enumeration deviceEnum = devices.elements();
System.out.println("Device count : " + devices.size());
while (deviceEnum.hasMoreElements()) {
CaptureDeviceInfo cdi = (CaptureDeviceInfo) deviceEnum.nextElement();
System.out.println("Device : " + cdi.getName());
}
}
The code for the VFWAuto class is given below. This is part of the JMStudio source code. You can get a good idea on how the devices are detected and recorded in the registry. Put both classes in the same package when you test. Disregard the main method in the VFWAuto class.
import com.sun.media.protocol.vfw.VFWCapture;
import java.util.*;
import javax.media.*;
public class VFWAuto {
public VFWAuto() {
Vector devices = (Vector) CaptureDeviceManager.getDeviceList(null).clone();
Enumeration enum = devices.elements();
while (enum.hasMoreElements()) {
CaptureDeviceInfo cdi = (CaptureDeviceInfo) enum.nextElement();
String name = cdi.getName();
if (name.startsWith("vfw:"))
CaptureDeviceManager.removeDevice(cdi);
}
int nDevices = 0;
for (int i = 0; i < 10; i++) {
String name = VFWCapture.capGetDriverDescriptionName(i);
if (name != null && name.length() > 1) {
System.err.println("Found device " + name);
System.err.println("Querying device. Please wait...");
com.sun.media.protocol.vfw.VFWSourceStream.autoDetect(i);
nDevices++;
}
}
}
public static void main(String [] args) {
VFWAuto a = new VFWAuto();
System.exit(0);
}
}
Assuming you are on a Windows platform and you have a working web-cam, then this code should detect the device and populate the jmf.properties file. On the next run you can also comment out the VFWAuto section and it's object references and you can see that CaptureDeviceManager reads from the jmf.properties file.
The VFWAuto class is part of jmf.jar. You can also see the DirectSoundAuto and JavaSoundAuto classes for detecting audio devices in the JMStudio sample source code. Try it out the same way as you did for VFWAuto.
My configuration was Windows 7 64 bit + JMF 2.1.1e windows performance pack + a web-cam.
I had the same issue and I solved by invoking flush() on my ObjectInputStream object.
According to the API documentation for ObjectInputStream's constructor:
The stream header containing the magic number and version number are read from the stream and verified. This method will block until the corresponding ObjectOutputStream has written and flushed the header.
This is a very important point to be aware of when trying to send objects in both directions over a socket because opening the streams in the wrong order will cause deadlock.
Consider for example what would happen if both client and server tried to construct an ObjectInputStream from a socket's input stream, prior to either constructing the corresponding ObjectOutputStream. The ObjectInputStream constructor on the client would block, waiting for the magic number and version number to arrive over the connection, while at the same time the ObjectInputStream constructor on the server side would also block for the same reason. Hence, deadlock.
Because of this, you should always make it a practice in your code to open the ObjectOutputStream and flush it first, before you open the ObjectInputStream. The ObjectOutputStream constructor will not block, and invoking flush() will force the magic number and version number to travel over the wire. If you follow this practice in both your client and server, you shouldn't have a problem with deadlock.
Credit goes to Tim Rohaly and his explanation here.
Before calling CaptureDeviceManager.getDeviceList(), the available devices must be loaded into the memory first.
You can do it manually by running JMFRegistry after installing JMF.
or do it programmatically with the help of the extension library FMJ (Free Media in Java). Here is the code:
import java.lang.reflect.Field;
import java.util.Vector;
import javax.media.*;
import javax.media.format.RGBFormat;
import net.sf.fmj.media.cdp.GlobalCaptureDevicePlugger;
public class FMJSandbox {
static {
System.setProperty("java.library.path", "D:/fmj-sf/native/win32-x86/");
try {
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
GlobalCaptureDevicePlugger.addCaptureDevices();
Vector deviceInfo = CaptureDeviceManager.getDeviceList(new RGBFormat());
System.out.println(deviceInfo.size());
for (Object obj : deviceInfo ) {
System.out.println(obj);
}
}
}
Here is the output:
USB2.0 Camera : civil:\\?\usb#vid_5986&pid_02d3&mi_00#7&584a19f&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global
RGB, -1-bit, Masks=-1:-1:-1, PixelStride=-1, LineStride=-1

Categories