|
When posting your question please:- Choose the correct forum for your message. Posting a VB.NET question in the C++ forum will end in tears.
- Be specific! Don't ask "can someone send me the code to create an application that does 'X'. Pinpoint exactly what it is you need help with.
- Keep the subject line brief, but descriptive. eg "File Serialization problem"
- Keep the question as brief as possible. If you have to include code, include the smallest snippet of code you can.
- Be careful when including code that you haven't made a typo. Typing mistakes can become the focal point instead of the actual question you asked.
- Do not remove or empty a message if others have replied. Keep the thread intact and available for others to search and read. If your problem was answered then edit your message and add "[Solved]" to the subject line of the original post, and cast an approval vote to the one or several answers that really helped you.
- If you are posting source code with your question, place it inside <pre></pre> tags. We advise you also check the "Encode HTML tags when pasting" checkbox before pasting anything inside the PRE block, and make sure "Ignore HTML tags in this message" check box is unchecked.
- Be courteous and DON'T SHOUT. Everyone here helps because they enjoy helping others, not because it's their job.
- Please do not post links to your question in one forum from another, unrelated forum (such as the lounge). It will be deleted.
- Do not be abusive, offensive, inappropriate or harass anyone on the boards. Doing so will get you kicked off and banned. Play nice.
- If you have a school or university assignment, assume that your teacher or lecturer is also reading these forums.
- No advertising or soliciting.
- We reserve the right to move your posts to a more appropriate forum or to delete anything deemed inappropriate or illegal.
When answering a question please:
- Read the question carefully
- Understand that English isn't everyone's first language so be lenient of bad spelling and grammar
- If a question is poorly phrased then either ask for clarification, ignore it, or mark it down. Insults are not welcome
- If the question is inappropriate then click the 'vote to remove message' button
Insults, slap-downs and sarcasm aren't welcome. Let's work to help developers, not make them feel stupid.
cheers,
Chris Maunder
The Code Project Co-fou
|
|
|
|
|
I heard that Java string characters are 16-bit. Is this true?
Does this mean that certain Unicode characters can't be represented since there are about 150,000 Unicode characters?
Thank you.
|
|
|
|
|
|
|
Being an old codger, I find Google is quite intelligent enough for me.
|
|
|
|
|
That is an incomplete question.
First for java a string contains a character set. So whatever that character set does is what java does.
From the other response the relevant part then is the following
"A String represents a string in the UTF-16 format in which supplementary characters are represented by surrogate pairs"
You would need to look up 'surrogate pairs' to understand that.
In practical business programming however that is not generally relevant. I know for example that Egyptian hieroglyphics are in the extended set. Certainly Americas, Europe, most of Asia is in the normal set. Not sure about Japanese (etc) like Kanji might or might not be. But supporting those requires other business changes also.
In practical business programming, with anything except English you still must be careful how you store (database) the text. A 'varchar' does represent a character set and you better understand the implications of that before making a decision on what to use. Just a general easy decision to make everything UTF in a database is not necessarily a good idea and there can be unexpected implications of making that decision.
|
|
|
|
|
jschell wrote: In practical business programming, with anything except English You should not exclude English. Even if you and your company's home is in the USA, and you do all your business correspondence in English, you soon run into partners - persons or organizations - with names or addresses using characters outside 7-bit ASCII. Under some circumstances, simply replacing non-ASCII characters with whatever ASCII character you think resembles the original most closely can lead to misunderstandings and failure to find essential information in a search. Sometimes, the replacement can lead to what is in the original language a rude word, an insult etc.
UTF-8 always could handle the entire Unicode range, and for most of your text (if you don't have any business contacts with non-ASCII names or addresses, it goes for all of it), UTF-8 is just as compact as ASCII (*). If your software uses UTF-16 as an internal format, the best thing is if it can handle surrogates, but you can get a long way with handling the basic plane only. (Until you go crazy with emoticons, using all there is available - but that is not too common in business correspondence).
(*) Certainly: ASCII can be transmitted over a US style 56 kbps digital line, with 7 bits to the character. UTF-8 cannot; it requires 8 bits per byte. Even US digital lines were 8 bits per byte, 64 kbps, but for every 6 byte, the phone switch stole the LSB to use for its communication with other switches, so only 7 of the 8 bits were reliable in data transfer. I don't know whether 56 kbps lines are still used in the US of A (please enlighten me!). If they are, you can send 7-bit ASCII untransformed, but not UTF-8. Most likely, it will be transformed anyway - there is a whole crowd of different standard ways of transforming any data stream to 7-bit bytes. MIME alone provides three alternatives!
|
|
|
|
|
Hello, good day, I have 2 problems.
1. I can't find the installation path or the option mentioned in this post doesn't appear.
https://stackoverflow.com/questions/20718093/eclipse-interface-icons-very-small-on-high-resolution-screen-in-windows-8-1
2. Modifying the eclipse .ini file actually enlarges the icons but deconfigures my entire eclipse.
How can I solve it? Thank you.
|
|
|
|
|
Isn't there a forum somewhere where else (not this site) for Eclipse questions?
|
|
|
|
|
Any suggestions in Java for the following scenario:
Actually its truncating trailing zeros when converting to double.
Ex-1:
String - "123.4000"
double - 123.4000
Ex-2:
String - "123.4560"
double - 123.4560
|
|
|
|
|
Well, I do not see any truncation in your question. But most likely you misunderstand the difference between the string representation of a number and its actual value. For example the number 1.5 , can be presented as a string with a number of trailing zeroes such as: "1.50", "1.5000" etc. But its value is still 1.5 .
|
|
|
|
|
I understand that, i am getting input in form of string, the same need to be converted to double and send with out ignoring trailing zeros. I think now I am more clear on requirement.
|
|
|
|
|
Member 16135433 wrote: I think now I am more clear on requirement. Sorry, no you are not clear. What do you mean by "converted to double and send with out ignoring trailing zeros"? A double value, as I mentioned in my first reply, does not have trailing zeroes, it is just a number. How and where are you trying to send these numbers?
|
|
|
|
|
Quote: converted to double and send
No, not clear at all. What are you "sending" this data to?
All numerical types do not track trailing zeros, so whatever you're sending this data to must accept the values as strings, not a double type.
|
|
|
|
|
Member 16135433 wrote: the same need to be converted to double and send with out ignoring trailing zeros
Breaking that down into steps
1. String arrives
2. Convert to double
3. Something happens????
4. Then "send".
Unless something happens at step 3 which you did not define then of course you do not need to convert it in the first place.
That is because "send" in the modern world always means a string. XML, HTML, Json, even many other representations in TCP/IP will always be a string.
The only time when that is not true is when you are using a binary format and there can be all sorts for complications with that (precision, big versus, little, etc)
So presuming there is in fact a real need to handle it as a double then when you "send" it you must format it correctly. Just as though you started with a double in first place. In other words how it arrives is irrelevant.
|
|
|
|
|
|
There is no such thing as a value "with trailing zeros". "Trailing zeros" is a presentation thing, when you show the value in your UI, not a representation thing in a floating-point variable.
|
|
|
|
|
I found the following code posted by @Richard-MacCutchan to a thread about how to use JNI without having to add the location of jvm.dll into Environment Variables. I kinda understood how it works but still...
#include <Windows.h>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <filesystem> // requires -std:c++17
#include "jni.h"
HMODULE LoadDll(
const char* jrePath
)
{
const char* pszjvmname = "bin\\server\\jvm.dll"; HMODULE hJVMDLL = 0;
std::filesystem::path jvmpath(jrePath);
jvmpath /= pszjvmname;
if (!std::filesystem::exists(jvmpath))
{
std::cerr << "JVM library " << jvmpath << " not found." << std::endl;
}
hJVMDLL = LoadLibraryW(reinterpret_cast<PCWSTR>(jvmpath.c_str()));
if (hJVMDLL != NULL)
{
std::clog << "jvm.dll loaded from: " << jvmpath << std::endl;
}
return hJVMDLL; }
JNIEnv* AttachJVM(
const char* jrePath,
JavaVM* jvm,
std::string strcwd
)
{
HMODULE hJVMDLL = LoadDll(jrePath);
if (hJVMDLL == 0)
{
return nullptr;
}
typedef jint(JNICALL* fpCJV)(JavaVM**, void**, void*);
fpCJV JNI_CreateJavaVM = (fpCJV)::GetProcAddress(hJVMDLL, "JNI_CreateJavaVM");
JavaVMOption options[2];
std::stringstream ssoptions;
ssoptions << "-Djava.class.path=";
ssoptions << strcwd;
std::string stropts = ssoptions.str();
options[0].optionString = const_cast<char*>(stropts.c_str());
options[1].optionString = const_cast<char*>("-verbose:jni");
JavaVMInitArgs vm_args; vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 1; vm_args.ignoreUnrecognized = false;
vm_args.options = options;
for (int i = 0; i < vm_args.nOptions; ++i)
{
std::clog << "Options[" << i << "]: " << options[i].optionString << std::endl;
}
JNIEnv* env; jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if (res != 0)
{
std::cerr << "C++: JNI_CreateJavaVM returned: " << res << std::endl;
}
jint version = env->GetVersion();
std::clog << "JVM Version: " << (version >> 16) << "." << (version & 0xffff) << std::endl;
return env; }
void CallClass(
JNIEnv* jniEnv,
const char* pszClassname,
const char* pszMethodname,
const char* pszSignature
)
{
jclass jvmclass = jniEnv->FindClass(pszClassname);
if (jvmclass != NULL)
{
std::cout << "C++: Found the class: " << pszClassname << std::endl;
jmethodID jmid = jniEnv->GetStaticMethodID(jvmclass, pszMethodname, pszSignature);
if (jmid != NULL)
{
std::cout << "C++: Found the method: " << pszMethodname << std::endl;
jniEnv->CallStaticVoidMethod(jvmclass, jmid, NULL);
std::cout << "C++: env->CallStaticVoidMethod complete" << std::endl;
}
else
{
std::cerr << "C++: Failed to find the method: " << pszMethodname << std::endl;
}
}
else
{
std::cerr << "C++: Failed to find the class: " << pszClassname << std::endl;
}
}
int main(
int argc,
const char** argv
)
{
const char* jreDir = nullptr;
std::clog.setstate(std::ios::badbit);
for (argv++; argc > 1; ++argv, --argc)
{
if (*argv[0] == '-')
{
if (strstr(*argv, "-d"))
std::clog.clear();
}
else
{
jreDir = *argv;
}
}
if (jreDir == nullptr)
{
std::cerr << "No root path provided for JVM." << std::endl;
return 1;
}
JNIEnv* jniEnv = NULL;
std::filesystem::path cwd = std::filesystem::current_path();
JavaVM jvm;
jniEnv = AttachJVM(jreDir, &jvm, cwd.string());
if (jniEnv == NULL)
{
std::cerr << "C++: Failed to get Java environment" << std::endl;
return 1;
}
CallClass(jniEnv, "CppToJava", "main", "([Ljava/lang/String;)V");
jint jvmres = jvm.DestroyJavaVM(); std::clog << "C++: DestroyJavaVM and terminate: " << jvmres << std::endl;
}
I have two minor problems, I get a bit lost, I understand that it looks to see if Java in installed and tries to get the path to it and then to load the DLL, but I didn't managed to make it work for my situation, and also, on client machines I'm not making them install Java, but it comes in the app files with a license agreement, I'm using Eclipse Adoptium (...\MyApp\ThirdParty\Eclipse Adoptium\jre-17.0.7.7-hotspot).
If it isn't much to ask, could someone help me change the above code so that it will work in this scenario: Before creating the JVM, I'm running some other functions, and one of them returns the location for the app folder (ex: D:\Program Files\MyApp). Inside that folder are the apps data, and a folder Data, inside it a folder Java, and inside that all the java class files (...\MyApp\Data\Java\JavaMethods.class). So because I know the location of the app, I can give the location for jvm.dll by using the variable std::string location which would have as an example D:\Program Files\MyApp, then to that I can append \ThirdParty\Eclipse Adoptium\jre-17.0.7.7-hotspot\bin\server for the location of jvm.dll.
To be more precise, what I need to add before location.insert(0, "-Djava.class.path=");, to load the jvm.dll knowing it's location by combining like I said, the value from function parameter which would be set before calling the function and would have as an example D:\Program Files\MyApp, with \ThirdParty\Eclipse Adoptium\jre-17.0.7.7-hotspot\bin\server.
Here is an example how my app is using JNI extracted to a new project:
#include <jni.h>
#include <string>
#include <iostream>
#include <chrono>
#include <thread>
JavaVM* jvm = nullptr;
std::string createVM(std::string location) {
location.insert(0, "-Djava.class.path=");
location.append("Data\\Java");
JavaVMInitArgs vm_args;
JavaVMOption* options = new JavaVMOption[1];
options[0].optionString = &location[0];
vm_args.version = JNI_VERSION_10;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
JNIEnv* env = nullptr;
jint rc = JNI_OK;
if (jvm == nullptr) {
rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
}
else {
rc = jvm->AttachCurrentThread((void**)&env, NULL);
}
delete[] options;
if (rc != JNI_OK) {
if (rc == JNI_EVERSION)
return "JNI_EVERSION";
else if (rc == JNI_ENOMEM)
return "JNI_ENOMEM";
else if (rc == JNI_EINVAL)
return "JNI_EINVAL";
else if (rc == JNI_EEXIST)
return "JNI_EEXIST";
else
return "JNI_FATALERROR";
}
return "JNI_CREATED";
}
std::string createIdentification() {
JNIEnv* env;
jvm->AttachCurrentThread((void**)&env, NULL);
jclass jClass = env->FindClass("JavaMethods");
if (jClass == nullptr) {
return "ClassNotFound cI";
}
else {
jmethodID methodID = env->GetStaticMethodID(jClass, "createIdentification", "()Ljava/lang/String;");
if (methodID == nullptr) {
return "MethodNotFound cI";
}
else {
jboolean isCopy;
jstring jResult = (jstring)env->CallStaticObjectMethod(jClass, methodID);
const char* string = env->GetStringUTFChars(jResult, &isCopy);
std::string result = string;
env->ReleaseStringUTFChars(jResult, string);
return result;
}
}
}
int main() {
std::cout << createVM("D:\\Program Files\\MyApp\\").c_str() << std::endl;
std::cout << createIdentification().c_str();
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
return 0;
}
|
|
|
|
|
 I managed to make it work:
#include <string>
#include <iostream>
#include <chrono>
#include <thread>
#include <jni.h>
#include <Windows.h>
JavaVM* jvm = nullptr;
std::string createVM(std::string location) {
std::string jvmLocation = location;
jvmLocation.append("ThirdParty\\Eclipse Adoptium\\jre-17.0.7.7-hotspot\\bin\\servers\\jvm.dll");
HMODULE hJVMDLL = LoadLibraryA(jvmLocation.c_str());
typedef jint(JNICALL* fpCJV)(JavaVM**, void**, void*);
if (hJVMDLL != NULL) {
fpCJV JNI_CreateJavaVM = (fpCJV)::GetProcAddress(hJVMDLL, "JNI_CreateJavaVM");
location.insert(0, "-Djava.class.path=");
location.append("Data\\Java");
JavaVMInitArgs vm_args;
JavaVMOption* options = new JavaVMOption[1];
options[0].optionString = &location[0];
vm_args.version = JNI_VERSION_10;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
JNIEnv* env = nullptr;
jint rc = JNI_OK;
if (jvm == nullptr) {
rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
}
else {
rc = jvm->AttachCurrentThread((void**)&env, NULL);
}
delete[] options;
if (rc != JNI_OK) {
if (rc == JNI_EVERSION)
return "JNI_EVERSION";
else if (rc == JNI_ENOMEM)
return "JNI_ENOMEM";
else if (rc == JNI_EINVAL)
return "JNI_EINVAL";
else if (rc == JNI_EEXIST)
return "JNI_EEXIST";
else
return "JNI_FATALERROR";
}
return "JNI_CREATED";
}
else {
return "ERROR_LOADING_DLL";
}
}
std::string createIdentification() {
JNIEnv* env;
jvm->AttachCurrentThread((void**)&env, NULL);
jclass jClass = env->FindClass("JavaMethods");
if (jClass == nullptr) {
return "ClassNotFound cI";
}
else {
jmethodID methodID = env->GetStaticMethodID(jClass, "createIdentification", "()Ljava/lang/String;");
if (methodID == nullptr) {
return "MethodNotFound cI";
}
else {
jboolean isCopy;
jstring jResult = (jstring)env->CallStaticObjectMethod(jClass, methodID);
const char* string = env->GetStringUTFChars(jResult, &isCopy);
std::string result = string;
env->ReleaseStringUTFChars(jResult, string);
return result;
}
}
}
int main() {
std::cout << createVM("Location_To_App_Folder").c_str() << std::endl;
if (jvm != NULL) {
std::cout << createIdentification().c_str();
}
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
return 0;
}
Thank you @Richard-MacCutchan for the original code!
|
|
|
|
|
Valentinor wrote: I'm not making them install Java
That is oddly phrased since they will need to have java installed somehow.
As a suggestion only you might want to work on your error handling if it turns out Java isn't installed. Telling a user that a dll is missing is not going to help them nor you when they ask why it isn't working. You might want to also print where you looked when you can't find it.
|
|
|
|
|
jschell wrote: That is oddly phrased since they will need to have java installed somehow.
Why did you stopped there with the quote? As the next part of the phrase contained the reason why I'm not making the install Java:
Valentinor wrote: but it comes in the app files with a license agreement, I'm using Eclipse Adoptium (...\MyApp\ThirdParty\Eclipse Adoptium\jre-17.0.7.7-hotspot).
So yeah, they don't need to install java, as it is included with the app.
|
|
|
|
|
Valentinor wrote: So yeah, they don't need to install java,
On Windows a Java install consists basically of the following.
1. Lay down the files into the file system.
2. Create the registry data so the user can uninstall it.
So apparently what you are actually doing is giving the user the option to use the Java that is already installed or to use the VM that comes with your application.
Besides my other suggestion you might also want to consider whether the VM they have installed is the correct version for your appliction.
|
|
|
|
|
jschell wrote: 1. Lay down the files into the file system.
Yes or no, depending what you mean by "file system". When the app is installed, inside it's folder structure it will also have Eclipse Adoptium (...\MyApp\ThirdParty\Eclipse Adoptium\jre-17.0.7.7-hotspot)
jschell wrote: 2. Create the registry data so the user can uninstall it.
It will be for the app itself and not just for java, as Eclipse Adoptium will be a part of the app, integrated into it, and not separate. When the app is uninstalled, so will Eclipse Adoptium as it is part of its files. If the user has any other form of Java installed, they won't be affected in any way.
jschell wrote: So apparently what you are actually doing is giving the user the option to use the Java that is already installed or to use the VM that comes with your application.
No. The app will only use Java that comes with it, as the app won't even look in another location if Java is installed, only inside it's file structure.
jschell wrote: whether the VM they have installed is the correct version for your appliction
I explained in the above statement why this doesn't matter for my case.
jschell wrote: As a suggestion only you might want to work on your error handling if it turns out Java isn't installed. Telling a user that a dll is missing is not going to help them nor you when they ask why it isn't working.
I never said that I don't have an error handling system already added. If any of Java files are missing or are corrupted, or any of the other app files are missing or are corrupted, an error will appear telling the user to run the check for corrupted files or reinstall the app, accompanied by an error message, that will tell me exactly which file is the problem, if it is missing or if it is corrupted.
|
|
|
|
|
I have a socket though which I'm sending files. If the file is under the buffer size (8192 in my case) then it is fine, but if the file is over that size, then when it writes to file, it writes the first chunk of 8192 bites every time. I'm using ObjectStream because beside the file, I'm sending other objects as well in the actual app, but this is the part of sending the file.
Client it sends the file data (testing):
System.out.println("Starting client");
Socket socket = new Socket("localhost", port);
System.out.println("Client sending data");
ObjectOutputStream dataOut = new ObjectOutputStream(socket.getOutputStream());
BufferedInputStream is = new BufferedInputStream(new FileInputStream(inFile));
byte[] buffer = new byte[8192];
int sizeRead = 0;
while ((sizeRead = is.read(buffer, 0, 8192)) >= 0) {
printByte(buffer, "in");
dataOut.writeObject(true);
dataOut.writeObject(buffer);
dataOut.writeObject(sizeRead);
dataOut.flush();
}
is.close();
System.out.println("Done sending file");
dataOut.writeObject(false);
socket.close();
System.out.println("Client closed");
Server that creates the file:
System.out.println("Starting server");
ServerSocket server = new ServerSocket(port);
System.out.println("Server waiting");
Socket socket = server.accept();
System.out.println("Client connected");
ObjectInputStream dataIn = new ObjectInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outFile));
Object auxKeepReading = dataIn.readObject();
if (auxKeepReading instanceof Boolean) {
while ((boolean) auxKeepReading) {
Object auxBuffer = dataIn.readObject();
if (!(auxBuffer instanceof byte[])) {
System.out.println("Broke byte");
break;
}
Object auxSize = dataIn.readObject();
if (!(auxSize instanceof Integer)) {
System.out.println("Broke int");
break;
}
printByte((byte[]) auxBuffer, "out");
bos.write((byte[]) auxBuffer, 0, (int) auxSize);
auxKeepReading = dataIn.readObject();
if (!(auxKeepReading instanceof Boolean)) {
System.out.println("Broke boolean");
break;
}
}
} else {
System.out.println("Broke boolean");
}
bos.close();
socket.close();
server.close();
System.out.println("Server stopped");
Why is it that it keeps sending the first chunk of byte[], and not what it reads new?
|
|
|
|
|
On client side after sending the size that it read, I added buffer = new byte[8192]; and now I don't have the problem and it is sending new data but there are 2 problems:
1. I don't know if this is what you should do;
2. The speed is limited to 3 MB/s when using IP instead of localhost, on an internet connection of 1.000 Mbps (~125 MB/s) upload/download (they are the same). I tried to increase the buffer size but still the same speed.
|
|
|
|
|