МАРК РЕГНЕРУС ДОСЛІДЖЕННЯ: Наскільки відрізняються діти, які виросли в одностатевих союзах
РЕЗОЛЮЦІЯ: Громадського обговорення навчальної програми статевого виховання ЧОМУ ФОНД ОЛЕНИ ПІНЧУК І МОЗ УКРАЇНИ ПРОПАГУЮТЬ "СЕКСУАЛЬНІ УРОКИ" ЕКЗИСТЕНЦІЙНО-ПСИХОЛОГІЧНІ ОСНОВИ ПОРУШЕННЯ СТАТЕВОЇ ІДЕНТИЧНОСТІ ПІДЛІТКІВ Батьківський, громадянський рух в Україні закликає МОН зупинити тотальну сексуалізацію дітей і підлітків Відкрите звернення Міністру освіти й науки України - Гриневич Лілії Михайлівні Представництво українського жіноцтва в ООН: низький рівень культури спілкування в соціальних мережах Гендерна антидискримінаційна експертиза може зробити нас моральними рабами ЛІВИЙ МАРКСИЗМ У НОВИХ ПІДРУЧНИКАХ ДЛЯ ШКОЛЯРІВ ВІДКРИТА ЗАЯВА на підтримку позиції Ганни Турчинової та права кожної людини на свободу думки, світогляду та вираження поглядів
Контакти
Тлумачний словник Авто Автоматизація Архітектура Астрономія Аудит Біологія Будівництво Бухгалтерія Винахідництво Виробництво Військова справа Генетика Географія Геологія Господарство Держава Дім Екологія Економетрика Економіка Електроніка Журналістика та ЗМІ Зв'язок Іноземні мови Інформатика Історія Комп'ютери Креслення Кулінарія Культура Лексикологія Література Логіка Маркетинг Математика Машинобудування Медицина Менеджмент Метали і Зварювання Механіка Мистецтво Музика Населення Освіта Охорона безпеки життя Охорона Праці Педагогіка Політика Право Програмування Промисловість Психологія Радіо Регилия Соціологія Спорт Стандартизація Технології Торгівля Туризм Фізика Фізіологія Філософія Фінанси Хімія Юриспунденкция |
|
|||||||
Робота з файловою системою. Клас FileПлан План 1 Підключення зовнішніх бібліотек DLL. «Рідні» (native)методи
1 Підключення зовнішніх бібліотек DLL. «Рідні» (native) методи Для прикладного програмування засобів Java у переважній більшості випадків вистачає. Однак іноді виникає необхідність підключити до програми ряд системних викликів. Або забезпечити доступ до бібліотек, написаним на інших мовах програмування. Для таких цілей в Java використовуються методи, оголошені з модифікатором native - "рідний". Це слово означає, що при виконанні методу виробляється виклик "рідного" для конкретної платформи двійкового коду, а не платформо-незалежного байта-коду як у всіх інших випадках. Заголовок "рідного" методу описується в класі Java, а його реалізація здійснюється на якому-небудь із мов програмування, що дозволяють створювати бібліотеки, що підключаються динамічно (DLL - Dynamic Link Library під Windows, Shared Objects під UNIX-Образними операційними системами). Правило для оголошення й реалізації таких методів зветься JNI - Java Native Interface. Оголошення "рідного" методу в Java має вигляд
Модифікатори native Повертаємий_типім.’я_методу(список параметрів);
Тіло «рідного» методу не задається - воно є зовнішнім і завантажується на згадку комп'ютера за допомогою завантаження тої бібліотеки, з якої цей метод повинен викликатися:
System.loadLibrary(«Ім’я_бібліотеки»);
При цьому ім'я бібліотеки задається без шляху й без розширення. Наприклад, якщо під Windows бібліотека має ім'я myLib.dll, або під UNIX або Linux має ім'я myLib.so, треба вказувати System.loadLibrary(«myLib») ; У випадку, якщо файлу не знайдено, збуджується непроверяемая виняткова ситуація UnsatisfiedLinkError. Якщо потрібно вказати ім'я бібліотеки зі шляхом, застосовується виклик
System.load («Ім’я_бібліотеки_з_шляхом»);
Який у всім іншому абсолютно аналогічний виклику loadLibrary. Після того, як бібліотека завантажена, з погляду використання в програмі виклик "рідного" методу нічим не відрізняється від виклику будь-якого іншого методу. Для створення бібліотеки з методами, призначеними для роботи в якості "рідних", звичайно використовується мова С++. В JDK існує утиліта javah.exe, призначена для створення заголовків C++ зі скомпільованих класів Java. Покажемо, як їй користуватися, на прикладі класу ClassWithNativeMethod. Задамо його в пакеті нашого додатка:
package java_example_pkg; public class ClassWithNativeMethod { /** Creates a new instance of ClassWithNativeMethod */ public ClassWithNativeMethod() { } public native void myNativeMethod(); }
Для того, щоб скористатися утилітою javah, скомпілюємо проект і перейдемо в папку build\classes. У ній будуть розташовуватися папка з пакетом нашого додатка java_example_pkg і папка META-INF. У режимі командного рядка виконаємо команду
javah.exe java_example_pkg.ClassWithNativeMethod
Задавати ім'я класу необхідно з повною кваліфікацією, тобто із вказівкою перед ним ім'я пакета. У результаті в папці з'явиться файл java_example_pkg_ClassWithNativeMethod.h з наступним умістом:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class java_example_pkg_ClassWithNativeMethod */ #ifndef _Included_java_example_pkg_ClassWithNativeMethod #define _Included_java_example_pkg_ClassWithNativeMethod #ifdef __cplusplus extern "C" { #endif /* * Class: java_example_pkg_ClassWithNativeMethod * Method: myNativeMethod * Signature: ()V */ JNIEXPORT void JNICALL Java_java_1example_1pkg_ClassWithNativeMethod_myNativeMethod (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
Функція Java_java_1example_1pkg_ClassWithNativeMethod_myNativeMethod(JNIEnv *, jobject), написана на C++, повинна забезпечувати реалізацію методу myNativeMethod() у класі Java. Ім'я функції C++ складається з: префікса Java, роздільника "_", модифікованого ім'я пакета (знаки підкреслення "_" заміняються на "_1"), роздільника "_", ім'я класу, роздільника "_", ім'я "рідного" методу. Перший параметр JNIEnv * у функції C++ забезпечує доступ "рідного" коду до параметрів і об'єктів, що передається з функції C++ в Java. Зокрема, для доступу до стеку. Другий параметр, jobject, - посилання на екземпляр класу, у якому заданий "рідний" метод, для методів об'єкта, і jclass - посилання на сам клас - для методів класу. У мові C++ немає посилань, але в Java всі змінні об'єктного типу є посиланнями. Відповідно, другий параметр ототожнюється із цієї змінної. У реалізації методу потрібно оголосити змінні. Наприклад, якщо ми будемо обчислювати квадрат переданого в метод значення й повертати як результат значення параметра, зведене у квадрат (приклад чисто навчальний), код реалізації функції на C++ буде виглядати так:
#include "java_example_pkg_ClassWithNativeMethod.h" JNIEXPORT jint JNICALL Java_java_1example_1pkg_ClassWithNativeMethod_myNativeMethod (JNIEnv *env, jobject obj, jint i ){ return i*i };
Відзначимо, що при роботі з рядками й масивами для одержання й передачі параметрів потрібно використовувати змінну env. Наприклад, одержання довжини цілого масиву, переданого в змінну jintArray intArr, буде виглядати так:
jsize length=(*env)->GetArrayLength(env, intArr);
Виділення пам'яті під переданий масив:
jint *intArrRef=(*env)->GetIntArrayElements(env, intArr,0);
Далі з масивом intArr можна працювати як зі звичайним масивом C++. Вивільнення пам'яті з-під масиву:
(*env)->ReleaseIntArrayElements(env, intArr, intArrRef ,0); Є аналогічні функції для доступу до елементів масивів всіх примітивних типів: GetBooleanArrayElements, GetByteArrayElements,..., GetDoubleArrayElements. Ці функції копіюють уміст масивів Java у нову область пам'яті, з якої і йде робота в C++. Для масивів об'єктів є не тільки функція GetObjectArrayElement, але й SetObjectArrayElement - для одержання й зміни окремих елементів таких масивів. Рядок Java jstring s перетвориться в масив символів C++ так:
const char *sRef=(*env)->GetStringUTFChars(env,s,0); Тема 14 Можливості Java для обміну і передачі інформації. Робота з файловою системою. Пакет java.io 1 Система введення/виведення. Потоки даних (stream) 2 Робота з файловою системою. Клас File
1 Система введення/виведення. Потоки даних (stream) Звичайно, частина обчислювальної платформи, що відповідає за обмін даними, так і називається - система введення/виведення. В Java вона представлена пакетом java.io (input/output). Реалізація системи ускладнюється не тільки широким спектром джерел і одержувачів даних, але ще й різними форматами передачі інформації. Нею можна обмінюватися у двійковому поданні, символьному або текстовому, із застосуванням деякого кодування (тільки для російської мови їх налічується більше 4), або передавати числа в різних поданнях. Доступ до даних може знадобитися як послідовний (наприклад, зчитування HTML-сторінки), так і довільний (складна робота з декількома частинами одного файлу). Найчастіше для підвищення продуктивності застосовується буферизація. В Java для опису роботи з введенням/виведенням використовується спеціальне поняття потік даних (stream). Потік даних пов'язаний з деяким джерелом, або приймачем, даних, здатним одержувати або надавати інформацію. Відповідно, потоки діляться на вхідні - читаючі дані й вихідні - передавальні (записуючі) дані. В Java потоки природно представляються об'єктами. Їх класи, саме й становлять основну частину пакета java.io. Вони досить різноманітні й відповідають за різну функціональність. Всі класи розділені на дві частини - одні здійснюють введення даних, інші - виведення. Існуючі стандартні класи допомагають вирішити більшість типових задач. Мінімальною «порцією» інформації є, як відомо, біт, що приймає значення 0 або 1. Традиційно використовується більша одиниця виміру – байт, що поєднує 8 біт. Таким чином, значення, представлене одним байтом, перебуває в діапазоні від 0 до 255, або, якщо використовувати знак, – від -128 до +127. Примітивний тип byte в Java у точності відповідає останньому - знаковому діапазону. Базові, найбільш універсальні, класи дозволяють зчитувати й записувати інформацію саме у вигляді набору байт. Щоб їх було зручно застосовувати в різних задачах, java.io містить також класи, що перетворять будь-які дані в набір байт. Наприклад, якщо потрібно зберегти результати обчислень - набір значень типу double - у файл, то їх можна спочатку перетворити в набір байт, а потім ці байти записати у файл. Аналогічні дії відбуваються й у ситуації, коли потрібно зберегти об'єкт (тобто його стан) - перетворення в набір байт і наступний їхній запис у файл. Зрозуміло, що при відновленні даних в обох розглянутих випадках виконуються зворотні дії - спочатку зчитується послідовність байт, а потім вона перетворюється в потрібний формат. На рис. 14.1 представлено ієрархії класів введення/виведення. Як і говорилося, всі типи поділені на дві групи. вхідні потоки, що представляють, класи успадковуються від InputStream, а вихідні - від OutputStream.
Якщо класи потоків здійснюють реальний запис і читання даних, то клас File - це допоміжний інструмент, покликаний забезпечити роботу з файлами й каталогами. Об'єкт класу File є абстрактним поданням файлу й шляхи до нього. Він установлює тільки відповідність із ним, при цьому для створення об'єкта неважливо, чи існує такий файл на диску. Після створення можна виконати перевірку, викликавши метод exists, що повертає значення true, якщо файл існує. Створення або видалення об'єкта класу File жодним чином не відображається на реальних файлах. Для роботи із умістом файлу можна одержати екземпляри File/OStream. Об'єкт File може вказувати на каталог (довідатися це можна шляхом виклику методу isDirectory). Метод list повертає список імен (масив String) файлів, що втримуються в ньому (якщо об'єкт File не вказує на каталог - буде повернутий null). Наступний приклад демонструє використання об'єктів класу File: import java.io.*;public class FileDemo { public static void findFiles(File file, FileFilter filter, PrintStream output) throws IOException{ if (file.isDirectory()) { File[] list = file.listFiles(); for (int i=list.length; ---іi>=0;) { findFiles(list[i], filter, output); } } else { if (filter.accept(file)) output.println("\t" + file.getCanonicalPath()); } } public static void main(String[] args) { class NameFilter implements FileFilter { private String mask; NameFilter(String mask) { this.mask = mask; } public boolean accept(File file){ return (file.getName().indexOf(mask)!=-1)?true:false; } } File pathFile = new File("."); String filterString = ".java"; try { FileFilter filter = new NameFilter(filterString); findFiles(pathFile, filter, System.out); } catch(Exception e) { e.printStackTrace(); } System.out.println("work finished"); }}
При виконанні цієї програми на екран будуть виведені назви (у канонічному виді) всіх файлів, з розширенням .java, що знаходяться в поточному каталозі й всіх його підкаталогах. Для визначення того, що файл має розширення .java, використовувався інтерфейс FileFilter з реалізацією у вигляді внутрішнього класу NameFilter. Інтерфейс FileFilter визначає тільки один метод accept, що повертає значення, яке визначає, чи попадає переданий файл в умови фільтрації. Крім цього інтерфейсу, існує ще один різновид інтерфейсу фільтра - FilenameFilter, де метод accept визначений трохи інакше: він приймає не об'єкт файлу до перевірки, а об'єкт File, що вказує на каталог, де перебуває файл для перевірки, і рядок його назви. Для перевірки збігу, з урахуванням регулярних виражень, потрібно відповідним чином реалізувати метод accept. В конкретному наведеному прикладі можна було обійтися й без використання інтерфейсів FileFilter або FilenameFilter. На практиці їх можна використовувати для виклику методів list об'єктів File - у цих випадках будуть повернуті файли з урахуванням фільтра. Також клас File надає можливість одержання деякої інформації про файл. - методи canRead і canWrite - повертають boolean значення, чи можна буде додатку робити читання й зміну вмісту з файлу;. - getName - повертає рядок - ім'я файлу (або каталогу); - getParent, getParentName - повертають каталог, де файл перебуває у вигляді об'єкта й рядка назви File, відповідно; - getPath - повертає шлях до файлу (при цьому в рядок перетвориться абстрактний шлях, на який указує об'єкт File); - isAbsolutely - повертає boolean значення, чи є абсолютним шлях, яким зазначений файл. Визначення, чи є шлях абсолютним, залежить від системи, де запущена Java-Машина. Так, для Windows абсолютний шлях починається із вказівки диска, або символом '\'. Для Unix абсолютний шлях починається символом '/' ; - isDirectory, isFile - повертає boolean значення, чи вказує об'єкт на каталог або файл, відповідно; - isHidden - повертає boolean значення, чи вказує об'єкт на схований файл; - lastModified - дата останньої зміни; - length - довжина файлу в байтах. Також можна змінити деякі властивості файлу - методи setReadOnly, setLastModified, призначення яких очевидно з назви. Якщо потрібно створити файл на диску, це дозволяють зробити методи createNewFile, mkDir, mkDirs. Відповідно, createNewFile створює порожній файл (якщо такий ще не існує), mkDir створює каталог, якщо для нього всі батьківські вже існують, а mkDirs створить каталог разом з усіма необхідними батьківськими. Файл можна й видалити - для цього призначені методи delete і deleteOnExit. При виклику методу delete файл буде вилучений відразу ж, а при виклику deleteOnExit по закінченні роботи Java-машини (тільки при коректному завершенні роботи) скасувати запит уже неможливо. Таким чином, клас File дає можливість досить повного керування файловою системою.
Читайте також:
|
||||||||
|