Ошибки компоновщика могут произойти, если заголовочный файл и связанная с ним общая библиотека (файл .lib) не синхронизируются. Позволь мне объяснить.
Как работают линкеры? Линкер соответствует объявлению функции (объявленному в заголовке) с его определением (в общей библиотеке) путем сравнения их подписи. Вы можете получить ошибку компоновщика, если компоновщик не найдет определение функции, которое идеально подходит.
Возможно ли получить ошибку компоновщика, даже если объявление и определение, похоже, совпадают? Да! Они могут выглядеть одинаково в исходном коде, но это действительно зависит от того, что видит компилятор. По сути, вы можете столкнуться с такой ситуацией:
// header1.h
typedef int Number;
void foo(Number);
// header2.h
typedef float Number;
void foo(Number); // this only looks the same lexically
Обратите внимание, что хотя обе декларации функций выглядят одинаково в исходном коде, но они действительно различаются в зависимости от компилятора.
Вы можете спросить, как это получается в такой ситуации? Включите пути, конечно! Если при компиляции разделяемой библиотеки путь include приводит к header1.h
, и вы в конечном итоге используете header2.h
в своей собственной программе, вы оставите царапины на своем заголовке, задаваясь вопросом, что произошло (каламбур).
Пример того, как это может произойти в реальном мире, объясняется ниже.
У меня есть два проекта: graphics.lib
и main.exe
. Оба проекта зависят от common_math.h
. Предположим, что библиотека экспортирует следующую функцию:
// graphics.lib
#include "common_math.h"
void draw(vec3 p) { ... } // vec3 comes from common_math.h
И затем вы идете вперед и включаете библиотеку в свой собственный проект.
// main.exe
#include "other/common_math.h"
#include "graphics.h"
int main() {
draw(...);
}
Boom! Вы получаете ошибку компоновщика, и вы понятия не имеете, почему она терпит неудачу. Причина в том, что общая библиотека использует разные версии одного и того же include common_math.h
(я сделал это очевидным здесь в этом примере, включив другой путь, но это может быть не всегда так очевидно. Возможно, путь include отличается в настройки компилятора).
Обратите внимание, что в этом примере компоновщик сказал бы вам, что не смог найти draw()
, когда на самом деле вы знаете, что он явно экспортируется библиотекой. Вы могли часами царапать себе голову, думая, что пошло не так. Дело в том, что компоновщик видит другую подпись, потому что типы параметров немного отличаются. В этом примере vec3
является другим типом в обоих проектах в отношении компилятора. Это может произойти из-за того, что они происходят из двух немного разных файлов include (возможно, включенные файлы поступают из двух разных версий библиотеки).
DUMPBIN - ваш друг, если вы используете Visual Studio. Я уверен, что другие компиляторы имеют другие подобные инструменты.
Процесс выглядит следующим образом:
[1] По проекту я имею в виду набор исходных файлов, которые связаны друг с другом для создания либо библиотеки, либо исполняемого файла .
РЕДАКТИРОВАТЬ 1: Переписать первый раздел, который будет легче понять. Пожалуйста, прокомментируйте ниже, чтобы сообщить мне, нужно ли что-то еще исправлять. Спасибо!
Самый простой способ: использовать gson, собственную библиотеку goo json в Google. https://code.google.com/p/google-gson/
Вот пример. Я перехожу на этот бесплатный сайт геолокатора и разбираю json и показываю свой почтовый индекс. (просто поместите этот материал в основной метод, чтобы проверить его)
String sURL = "http://freegeoip.net/json/"; //just a string
// Connect to the URL using java's native library
URL url = new URL(sURL);
URLConnection request = url.openConnection();
request.connect();
// Convert to a JSON object to print data
JsonParser jp = new JsonParser(); //from gson
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
JsonObject rootobj = root.getAsJsonObject(); //May be an array, may be an object.
String zipcode = rootobj.get("zip_code").getAsString(); //just grab the zipcode
Если вы не возражаете использовать несколько библиотек, это может быть сделано в одной строке.
Включить Apache Commons IOUtils & amp; json.org .
JSONObject json = new JSONObject(IOUtils.toString(new URL("https://graph.facebook.com/me"), Charset.forName("UTF-8")));
Я не уверен, что это эффективно, но это один из возможных способов:
Прочитать json из url use url.openStream()
и прочитать содержимое в строку.
построить объект JSON с этой строкой (подробнее в json.org )
JSONObject(java.lang.String source)
Construct a JSONObject from a source JSON text string.
Я сделал парсер json простейшим способом, вот он
package com.inzane.shoapp.activity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url) {
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
System.out.println(line);
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
System.out.println("error on parse data in jsonparser.java");
}
// return JSON String
return jObj;
}
}
этот класс возвращает объект json из url
, и если вы хотите, чтобы json-объект вы просто вызовите этот класс и метод в свой класс Activity
мой код здесь
String url = "your url";
JSONParser jsonParser = new JSONParser();
JSONObject object = jsonParser.getJSONFromUrl(url);
String content=object.getString("json key");
здесь «json key» обозначается как ключ в вашем json-файле
это простой пример json-файла
{
"json":"hi"
}
Здесь «json» является ключевым, а «hi» - значением
. Это приведет к тому, что ваше значение json будет содержать строковое содержимое.
Используйте HttpClient , чтобы захватить содержимое URL-адреса. А затем используйте библиотеку из json.org для разбора JSON. Я использовал эти две библиотеки для многих проектов, и они были прочными и простыми в использовании.
Помимо этого вы можете попробовать использовать java-библиотеку Facebook API. У меня нет опыта в этой области, но есть вопрос о переполнении стека, относящемся к , используя API Facebook в java . Вы можете посмотреть RestFB как хороший выбор для использования библиотеки.
Используя артефакт Maven org.json:json
, я получил следующий код, который, я думаю, довольно короткий. Не так короче, насколько это возможно, но все же можно использовать.
package so4308554;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import org.json.JSONException;
import org.json.JSONObject;
public class JsonReader {
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
public static void main(String[] args) throws IOException, JSONException {
JSONObject json = readJsonFromUrl("https://graph.facebook.com/19292868552");
System.out.println(json.toString());
System.out.println(json.get("id"));
}
}
Вот несколько альтернативных версий с Jackson (так как есть несколько способов, которыми вы могли бы хотеть данные как):
ObjectMapper mapper = new ObjectMapper(); // just need one
// Got a Java class that data maps to nicely? If so:
FacebookGraph graph = mapper.readValue(url, FaceBookGraph.class);
// Or: if no class (and don't need one), just map to Map.class:
Map<String,Object> map = mapper.readValue(url, Map.class);
И, в частности, обычная (IMO) случай, когда вы хотите иметь дело с объектами Java, может быть сделан одним лайнером:
FacebookGraph graph = new ObjectMapper().readValue(url, FaceBookGraph.class);
Другие библиотеки, такие как Gson, также поддерживают однострочные методы; почему многие примеры показывают, что более длинные разделы являются нечетными. И еще хуже то, что во многих примерах используется устаревшая библиотека org.json; это, возможно, было первым делом, но есть полдюжины лучших альтернатив, поэтому есть очень мало оснований для его использования.
Очень просто, используя jersey-client, просто включите эту зависимость maven:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.25.1</version>
</dependency>
Затем вызовите его, используя этот пример:
String json = ClientBuilder.newClient().target("http://api.coindesk.com/v1/bpi/currentprice.json").request().accept(MediaType.APPLICATION_JSON).get(String.class);
Затем используйте Google Gson для проанализировать JSON:
Gson gson = new Gson();
Type gm = new TypeToken<CoinDeskMessage>() {}.getType();
CoinDeskMessage cdm = gson.fromJson(json, gm);