मैंने डेल्फी समुदाय संस्करण का उपयोग करके एक प्रोग्राम (फ़ायरमोनकी) लिखा है। मैं प्रोग्राम को साझा करना चाहता हूं, लेकिन मेरे मित्र जिस .exe फ़ाइल को डाउनलोड कर रहे हैं, उसे स्ट्रिंग्स को पुनः प्राप्त करने के लिए समय-समय पर एक टेक्स्ट फ़ाइल तक पहुंचना होगा। प्रोग्राम लिखते समय मैंने स्टार्टअप पर टेक्स्ट फ़ाइल लोड करने के लिए एक ईवेंट हैंडलर का उपयोग किया:
Tform3.formCreate (प्रेषक: विषय); ... असाइनफाइल (माईफाइल, ('सी:******* ***।टेक्स्ट)); ...
डिजाइन चरण के दौरान ठीक काम किया।
एक शौक़ीन व्यक्ति के रूप में, मैं अब खुद को अटका हुआ पाता हूँ। यदि मैं एक इंस्टॉलेशन प्रोग्राम बनाने के लिए INNO सेटअप कंपाइलर का उपयोग करता हूं, जिसे मैं करने की योजना बना रहा हूं, तो मेरे पास डेटा फ़ाइल के स्थान पर यह वही हार्डवेयर्ड संदर्भ ('C:*****) नहीं हो सकता। मुझे उपरोक्त कोड को बदलने की आवश्यकता है जैसे कि .exe फ़ाइल सहायक डेटाफ़ाइल का पता लगा सकती है, भले ही वह .exe फ़ाइल (और डेटाफ़ाइल) किसी और के पीसी पर समाप्त हो।
मैं यह कैसे कर सकता हूँ? यानी मुझे कौन सा कोड चाहिए (उपरोक्त के स्थान पर) यह सुनिश्चित करने के लिए कि मैं जो इंस्टॉलेशन प्रोग्राम सौंपता हूं वह एक .exe फ़ाइल स्थापित करेगा जो डेटा फ़ाइल को संदर्भित कर सकता है?
कोई मदद, बहुत सराहना की। अभी भी सीख रहा।
4 जवाब
केवल पढ़ने के लिए पहुँच
यदि डेटा फ़ाइल हमेशा-पढ़ने के लिए मोड में खोली जानी चाहिए, तो सबसे आसान समाधान इसे *.exe फ़ाइल के बगल में रखना है। फिर, रनटाइम पर, आप गतिशील रूप से *.exe फ़ाइल का पथ ढूंढते हैं और डेटा फ़ाइल के पथ को खोजने के लिए इसे संशोधित करते हैं। उदाहरण के लिए,
uses
IOUtils;
procedure TForm1.FormCreate(Sender: TObject);
var
FileName: string;
begin
FileName := TPath.Combine(ExtractFilePath(ParamStr(0)), 'data.txt');
ShowMessage(TFile.ReadAllText(FileName, TEncoding.UTF8));
end;
ParamStr(0)
में *.exe फ़ाइल का पथ शामिल है, जैसे
'C:\Users\Andreas Rejbrand\Documents\Embarcadero\Studio\Projects\test\Win32\Debug\Project1.exe'
तब ExtractFilePath(ParamStr(0))
है
'C:\Users\Andreas Rejbrand\Documents\Embarcadero\Studio\Projects\test\Win32\Debug\'
और, अंत में, TPath.Combine(ExtractFilePath(ParamStr(0)), 'data.txt')
है
'C:\Users\Andreas Rejbrand\Documents\Embarcadero\Studio\Projects\test\Win32\Debug\data.txt'
सुनिश्चित करें कि इंस्टॉलर डेटा फ़ाइल को *.exe फ़ाइल के आगे रखता है।
पहुंच पढ़ें और लिखें
यदि हम एक सेटिंग फ़ाइल या किसी अन्य फ़ाइल के बारे में बात कर रहे हैं जिसे प्रत्येक उपयोगकर्ता को बदलने की आवश्यकता है (सॉफ़्टवेयर के माध्यम से), तो आप इसे *.exe फ़ाइल के बगल में नहीं रख सकते, क्योंकि *.exe फ़ाइल आमतौर पर प्रोग्राम फ़ाइलें फ़ोल्डर में रहती है, जो केवल पढ़ा जाता है। इसके अलावा, केवल एक प्रोग्राम फाइल फ़ोल्डर है, लेकिन संभवतः पीसी पर कई उपयोगकर्ता हैं, और प्रत्येक उपयोगकर्ता की अपनी प्रति होनी चाहिए।
समाधान यह है कि फ़ाइल को उपयोगकर्ता के स्वयं के फ़ोल्डरों में, विशेष रूप से, AppData
फ़ोल्डर में सहेजा जाए:
FileName := TPath.GetHomePath + '\Mariner\My Word Processor App\Settings\settings.ini';
(पथ निर्माण के लिए एक अलग दृष्टिकोण का उपयोग करके)।
मेरे सिस्टम पर, यह बन जाता है
'C:\Users\Andreas Rejbrand\AppData\Roaming\Mariner\My Word Processor App\Settings\settings.ini'
आपके इंस्टॉलर (इनो सेटअप) में इस स्थान पर फ़ाइलें रखने के लिए अंतर्निहित समर्थन है।
अपने लक्ष्य को प्राप्त करने के लिए आपके पास कई विकल्प हैं:
सबसे आसान तब होता है जब आप अपनी डेटा फ़ाइलों को उसी फ़ोल्डर में रखते हैं जिसमें EXE फ़ाइल होती है। फिर आप पथ को गतिशील रूप से प्राप्त करने के लिए
ExtractFilePath(ParamStr(0)) + 'NameOfFile.txt'
का उपयोग कर सकते हैं।
लेकिन अपनी फाइलों को लिखने के प्रति जागरूक रहें। यदि EXE को कहींC:\Programs (x86)
याC:\Programs
में रखा गया है, तो आप केवल फाइलों को लिख सकते हैं जब प्रोग्राम एलिवेटेड (व्यवस्थापक अधिकारों के साथ) चलता है! इस समस्या से बचने के लिए, EXE को किसी फ़ोल्डर में सीधेC:\
के नीचे रखें।यदि आप अपनी डेटा फ़ाइलों को किसी अन्य फ़ोल्डर में रखना चाहते हैं, उदा. कहीं
AppData
में, आप इस कोड का उपयोग कर सकते हैं:uses SHFolder; const CSIDL_COMMON_APPDATA = $0023; CSIDL_MYMUSIC = $000D; CSIDL_MYPICTURES = $0027; CSIDL_MYVIDEO = $000E; CSIDL_PROGRAM_FILES = $0026; CSIDL_PROGRAM_FILES_COMMON = $002B; CSIDL_SYSTEM = $0025; CSIDL_WINDOWS = $0024; type TSpecialFolder = ( // user folders sfUserAppData = CSIDL_APPDATA, // Anwendungsdaten: Ordner zur Ablage von Einstellungen für Anwendungsprogramme sfUserCookies = CSIDL_COOKIES, // Cookies sfUserDesktop = CSIDL_DESKTOPDIRECTORY, // Desktop sfUserDocuments = CSIDL_PERSONAL, // My files sfUserFavorites = CSIDL_FAVORITES, sfUserIEHistory = CSIDL_HISTORY, // Internet history sfUserIECache = CSIDL_INTERNET_CACHE, // "Temporary Internet Files" sfUserLocalAppData = CSIDL_LOCAL_APPDATA, sfUserMusic = CSIDL_MYMUSIC, sfUserNethood = CSIDL_NETHOOD, sfUserPictures = CSIDL_MYPICTURES, sfUserPrintHood = CSIDL_PRINTHOOD, sfUserProfile = CSIDL_PROFILE, // User folder C:\Users\<Username> sfUserRecent = CSIDL_RECENT, sfUserSendTo = CSIDL_SENDTO, sfUserStartMenuPrograms = CSIDL_PROGRAMS, // "Programs" in Startmenue sfUserStartMenu = CSIDL_STARTMENU, // Startmenue sfUserStartUp = CSIDL_STARTUP, // Startup in Startmenue sfUserTemplates = CSIDL_TEMPLATES, sfUserVideo = CSIDL_MYVIDEO, // All Users folders sfCommonAppData = CSIDL_COMMON_APPDATA, sfCommonDesktop = CSIDL_COMMON_DESKTOPDIRECTORY, sfCommonDocuments = CSIDL_COMMON_DOCUMENTS, sfCommonFavorites = CSIDL_COMMON_FAVORITES, sfCommonFiles = CSIDL_PROGRAM_FILES_COMMON, sfCommonMusic = CSIDL_COMMON_MUSIC, sfCommonPictures = CSIDL_COMMON_PICTURES, sfCommonStartMenuPrograms = CSIDL_COMMON_PROGRAMS, // "Programs" in Startmenue sfCommonStartMenu = CSIDL_COMMON_STARTMENU, sfCommonStartUp = CSIDL_COMMON_STARTUP, // Startup in Startmenue sfCommonVideo = CSIDL_COMMON_VIDEO, // system folders sfFonts = CSIDL_FONTS, sfProgramFiles = CSIDL_PROGRAM_FILES, sfSystem32 = CSIDL_SYSTEM, sfWindows = CSIDL_WINDOWS ); function GetSpecialFolder(const SpecialFolder: TSpecialFolder): string; const SHGFP_TYPE_CURRENT = 0; var Path: array [0 .. MAX_PATH] of char; begin if SUCCEEDED(SHGetFolderPath(0, Ord(SpecialFolder), 0, SHGFP_TYPE_CURRENT, @Path[0])) then result := Path else result := ''; end;
उदाहरण:
GetSpecialFolder(sfUserAppData) + 'YourFolder\NameOfFile.txt'
यदि इसे केवल पढ़ने के लिए ही एक्सेस किया जाता है, तो आप इसे निष्पादन योग्य में संसाधन के रूप में जोड़ने पर भी विचार कर सकते हैं। जो तब आपको इंस्टॉलर की आवश्यकता के बिना इस निष्पादन योग्य को वितरित करने की अनुमति देगा।
डेल्फी डब्बलर का एक उदाहरण है, लेकिन मुझे यह थोड़ा भ्रमित करने वाला लगा। मैं वैसे भी इससे लिंक (पीडीएफ) करूंगा।
आप उपयोगकर्ता को उस स्थान का चयन करने दे सकते हैं जहां फ़ाइल को सहेजना है। यदि फ़ाइल प्रत्येक व्यक्तिगत उपयोगकर्ता के लिए है या CommonAppData यदि फ़ाइल को विभिन्न उपयोगकर्ताओं के बीच साझा किया जाना है, तो AppData फ़ोल्डर का प्रस्ताव करना।
जब उपयोग डेटा फ़ाइल गंतव्य का चयन करता है, तो आप इसे एक आईएनआई फ़ाइल में सहेज सकते हैं। INI फ़ाइल को उपयोगकर्ता से पूछे बिना, रजिस्ट्री में या AppData फ़ोल्डर या प्रोग्रामडेटा फ़ोल्डर में सहेजी गई INI फ़ाइल में संग्रहीत किया जा सकता है।
यहाँ उन विशेष फ़ोल्डरों पर हाथ पाने के लिए स्रोत कोड का एक टुकड़ा दिया गया है:
const
SectionWindow = 'Window';
SectionData = 'Data';
CompanyFolder = 'YourCompanyName';
constructor TForm1.Create(AOwner: TComponent);
var
CommonPath : array [0..MAX_PATH] of Char;
LocalPath : array [0..MAX_PATH] of Char;
LangFileName : String;
begin
SHGetFolderPath(0, CSIDL_COMMON_APPDATA, 0, SHGFP_TYPE_CURRENT, @CommonPath[0]);
SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, SHGFP_TYPE_CURRENT, @LocalPath[0]);
FIniSection := SectionWindow;
FIniSectionData := SectionData;
FAppName := ChangeFileExt(ExtractFileName(Application.ExeName), '');
FCommonAppData := IncludeTrailingPathDelimiter(CommonPath) +
CompanyFolder + '\' + FAppName + '\';
FLocalAppData := IncludeTrailingPathDelimiter(LocalPath) +
CompanyFolder + '\' + FAppName + '\';
FIniFileName := FLocalAppData + FAppName + '.ini';
ForceDirectories(FCommonAppData);
ForceDirectories(FLocalAppData);
inherited Create(AOwner);
end;
संबंधित सवाल
नए सवाल
delphi
डेल्फी ऑब्जेक्ट पास्कल के उपयोग के माध्यम से देशी विंडोज, मैकओएस, लिनक्स, आईओएस और एंड्रॉइड अनुप्रयोगों के तेजी से विकास के लिए एक भाषा है। नाम डेल्फी भाषा के साथ-साथ इसके पुस्तकालयों, संकलक और आईडीई को संदर्भित करता है जो डेल्फी परियोजनाओं को संपादित करने और डिबग करने में मदद करने के लिए उपयोग किया जाता है।