Fiz uma aplicação em Java que le um arquivo de configuração, e se ele não existe, a aplicação cria.
Depois disso, fiz um instalador com o Inno Setup, que cria um atalho para a minha aplicação no desktop.
O problema é:
O arquivo de configuração está sendo criado no desktop, e isso não é o que eu quero. Isso acontece por que eu crio o arquivo no diretório “.”, que passa a ser o Desktop quando o programa é executado a partir do atalho.
Alguém sabe me dizer como fazer o .jar gerar o arquivo de configurações dentro da pasta que está o .jar? Essa pasta é dinâmica e depende da instalação. Estou procurando algum comando que me retorne a pasta real que o .jar está mas não estou conseguindo.
EDIT - Mesmo se for global eu recomendo usar o pacote prefs. Ele salva as configurações no registry no caso do Windows, e em arquivos XML no caso do Unix/Linux.
D
Damiao_Cunha
por padrão, vc encontrara o .jar na pasta do projeto, dentro da pasta “dist”…
pelo menos se for pelo netbeans é lá…
vlw
Augusto_
Achei uma solução, mas não fui muito com a cara dela…
Uma forma estúpida de obter isso é pegar, via getResource, a URL de algum recurso dentro desse JAR, e então pegar o nome do JAR a partir do objeto URL. que esse método retornou.
romarcio
Não sei que tipo de arquivo é o que está sendo criado, mas vc pode fazer algo assim:
O .getAbsoluteFile() que é um método da classe File vai criar seu arquivo no nivel da aplicação, ou seja, no mesmo diretório que estaria o pacote .jar de sua aplicação.
E
entanglement
romarcio:
O .getAbsoluteFile() que é um método da classe File vai criar seu arquivo…
getAbsoluteFile não cria arquivos
Ele apenas verifica se o File corresponde a um diretório ou arquivo existente no disco, e se corresponder, expande o diretório para o path completo.
Usar new File (".").getAbsoluteFile() só vai lhe retornar o diretório corrente, que pode ser o diretório onde você iniciou o JAR se você deu um duplo clique, ou então algum outro. Portanto, não é muito confiável.
O .getAbsoluteFile() que é um método da classe File vai criar seu arquivo…
getAbsoluteFile não cria arquivos
Ele apenas verifica se o File corresponde a um diretório ou arquivo existente no disco, e se corresponder, expande o diretório para o path completo.
Usar new File (".").getAbsoluteFile() só vai lhe retornar o diretório corrente, que pode ser o diretório onde você iniciou o JAR se você deu um duplo clique, ou então algum outro. Portanto, não é muito confiável.
A string s, vai passar pra ele o local exato de onde está o arquivo .jar, então ele poderá criar seu arquivo a partir desse diretório.
Augusto_
Esse
Filearquivo=newFile("arquivo.jar");if(arquivo.exists()){System.out.println(arquivo.getAbsolutePath());}else{System.out.println("O arquivo não existe");}
só irá funcionar se eu estiver rodando o .jar da pasta corrente dele. Caso contrário, ele irá retornar a pasta corrente com o nome “arquivo.jar” no final.
Exemplo:
estou no desktop: java -jar arquivo.jar -> retorna c:\users\augusto\desktop\arquivo.jar
estou na minha users: java -jar desktop\arquivo.jar -> retorna o arquivo não existe
Por enquanto a única solução que realmente funciona foi aquela solução bizzara que falei no começo:
Por que funciona? por que quando eu chamo PastaCorrente.class a máquina virtual do java pergunta diretamente à máquina virtual do java o nome do caminho do lugar aonde essa classe está no disco. Pra máquina virtual carregar, ela precisa saber esse endereço absoluto.
ViniGodoy
É virtualmente impossível descobrir o caminho onde está o .jar que disparou a aplicação, isso inclusive está na minha lista de coisas que odeio em Java. O java é feito justamente para você não ter esse caminho. Eu fiz um método que até funciona razoavelmente bem, e se baseia no que o Entanglement falou:
privatestaticStringfindJarParentPath(FilejarFile){while(jarFile.getPath().contains(".jar"))jarFile=jarFile.getParentFile();returnjarFile.getPath().substring(6);}/** * Return the instalation path of any class. * * @param theClass The class to find the installation path. * @return The installation path of any class. */publicstaticStringgetInstallPath(Class<?>theClass){Stringurl=theClass.getResource(theClass.getSimpleName()+".class").getPath();Filedir=newFile(url).getParentFile();if(dir.getPath().contains(".jar"))returnfindJarParentPath(dir).replace("%20"," ");returndir.getPath().replace("%20"," ");}
O uso é simples. Passe como parâmetro para o método qualquer classe que esteja dentro do pacote. Geralmente eu passo da minha classe onde está o main.
ViniGodoy
Ah sim, a solução ficou desajeitada justamente pq nosso security manager não permitia acesso ao protection domain.
Augusto_
O.o… acabei de dar uma solução que pergunta diretamente à JVM!
Eu só estou perguntando se alguém sabe uma solução que não precise dessa parafernalha toda…
E
entanglement
Se você puder usar o pacote java.util.prefs você nem precisa ficar com um arquivo de configuração, pode salvar as coisas no registry (no caso do Windows) ou em um arquivo XML (no caso do Linux/Unix). Isso pode ser interessante se você não quer que o pessoal fique mexendo com sua configuração.
13/07/2010 17:18:11 java.util.prefs.WindowsPreferences
WARNING: Could not create windows registry node Software\JavaSoft\Prefs\pasta/Corrente at root 0x80000002. Windows RegCreateKeyEx(…) returned error code 5.
13/07/2010 17:18:11 java.util.prefs.WindowsPreferences WindowsRegOpenKey1
WARNING: Trying to recreate Windows registry node Software\JavaSoft\Prefs\pasta/Corrente at root 0x80000002.
13/07/2010 17:18:11 java.util.prefs.WindowsPreferences openKey
WARNING: Could not open windows registry node Software\JavaSoft\Prefs\pasta/Corrente at root 0x80000002. Windows RegOpenKey(…) returned error code 2.
E
entanglement
Isso ocorre se sua aplicação não tiver as permissões corretas para criar algumas chaves no Registry. Portanto, você só pode criar configurações de sistema se você fizer isso durante a instalação.
ViniGodoy
Augusto_:
Rodem isso e vejam que funciona.
Eu só estou perguntando se alguém sabe uma solução que não precise dessa parafernalha toda…
vou mostrar denovo:
Por acaso você leu o que escrevi no post seguinte? Sua “solução” requisita o ProtectionDomain. Aproveite que você postou novamente o código, e leia-o.
Esse método só funciona se o SecurityManager autorizar e, como eu havia ressaltado no post seguinte, o nosso não autorizava.
E, como eu falei, no Java é virtualmente impossível achar esse caminho.
Por isso é necessário essa “parafernalha” toda, que geralmente não funcionam em todos os casos.